DCIPs/assets/eip-3267/contracts/SalaryWithDAO.sol

127 lines
5.0 KiB
Solidity

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.7.1;
import { ABDKMath64x64 } from "abdk-libraries-solidity/ABDKMath64x64.sol";
import "./BaseRestorableSalary.sol";
import "./DAOInterface.sol";
/// Salary system with a "DAO" that can assign attorneys to restore lost Ethereum accounts.
/// @author Victor Porton
/// @notice Not audited, not enough tested.
contract SalaryWithDAO is BaseRestorableSalary {
using ABDKMath64x64 for int128;
/// The DAO interface.
DAOInterface public daoPlugin;
/// When set to true, your account can't be moved to new address (by the DAO).
///
/// By default new users are not under DAO control to avoid front-running of resigning control
/// by an evil DAO.
///
/// Mapping (current address => under control)
mapping (address => bool) public underDAOControl;
/// Mapping (current address => account has at least one salary).
mapping (address => bool) public accountHasSalary;
// DAO share will be zero to prevent theft by voters and because it can be done instead by future voting.
// int128 public daoShare = int128(0).div(1); // zero by default
/// Constructor.
/// @param _daoPlugin The DAO interface.
/// @param _uri The ERC-1155 token URI.
constructor(DAOInterface _daoPlugin, string memory _uri)
BaseRestorableSalary(_uri)
{
daoPlugin = _daoPlugin;
}
/// Create an oracle for caclcualting salary amounts.
function createOracle() external returns (uint64) {
return _createOracle();
}
/// Register a salary recipient.
///
/// Can be called both before or after the oracle finish. However registering after the finish is useless.
///
/// Anyone can register anyone (useful for robots registering a person).
///
/// Registering another person is giving him money against his will (forcing to hire bodyguards, etc.),
/// but if one does not want, he can just not associate this address with his identity in his publications.
/// @param _customer The original address.
/// @param _oracleId The oracle ID.
/// @param _underDAOControl If the registered address will be under DAO control.
/// @param _data The current data.
function registerCustomer(address _customer, uint64 _oracleId, bool _underDAOControl, bytes calldata _data)
virtual public returns (uint256)
{
address _orig = _originalAddress(_customer);
// Auditor: Check that this value is set to false, when (and if) necessary.
accountHasSalary[_customer] = true;
underDAOControl[_customer] = _underDAOControl; // We don't trigger and event to reduce gas usage.
return super._registerCustomer(_orig, _oracleId, _data);
}
/// A user can agree for DAO control. Then his account can be restored by DAO for the expense
/// of the DAO assigned personnel or software being able to steal his funds.
///
/// Be exteremely careful calling this method: If you refuse and lose your key, your funds are lost!
///
/// Fishers may trick one to resign mistakenly. However, it's no much worse than just fishing for
/// withdrawing the salary token, because a user could just register anew and notify traders/oracles
/// that it's the same person.
function setDAOControl(bool _underControl) public {
address _orig = _originalAddress(msg.sender);
require(accountHasSalary[_orig], "Cannot resign account receiving a salary.");
underDAOControl[_orig] = _underControl; // We don't trigger and event to reduce gas usage.
}
/// The DAO can replace itself.
function setDAO(DAOInterface _daoPlugin) public onlyDAO {
daoPlugin = _daoPlugin;
}
/// Set the token URI.
function setURI(string memory _newuri) public onlyDAO {
_setURI(_newuri);
}
// Overrides ///
function checkAllowedRestoreAccount(address _oldAccount, address _newAccount)
public virtual override isUnderDAOControl(_oldAccount)
{
daoPlugin.checkAllowedRestoreAccount(_oldAccount, _newAccount);
}
/// Allow the user to unrestore by himself?
/// We won't not allow it to `_oldAccount` because it may be a stolen private key.
/// We could allow it to `_newAccount`, but this makes no much sense, because
/// it would only prevent the user to do a theft by himself, let only DAO could be allowed to do.
function checkAllowedUnrestoreAccount(address _oldAccount, address _newAccount)
public virtual override isUnderDAOControl(_oldAccount)
{
daoPlugin.checkAllowedUnrestoreAccount(_oldAccount, _newAccount);
}
// Internal //
function _isDAO() internal view returns (bool) {
return msg.sender == address(daoPlugin);
}
// Modifiers //
modifier onlyDAO() {
require(_isDAO(), "Only DAO can do.");
_;
}
/// @param _customer The current address.
modifier isUnderDAOControl(address _customer) {
require(underDAOControl[_customer], "Not under DAO control.");
_;
}
}