DCIPs/assets/eip-4886/contracts/ProxyRegister.sol

348 lines
12 KiB
Solidity

// SPDX-License-Identifier: CC0-1.0
// EPSProxy Contracts v1.7.0 (epsproxy/contracts/ProxyRegister.sol)
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@epsproxy/contracts/EPS.sol";
/**
* @dev The EPS Register contract.
*/
contract ProxyRegister is EPS, Ownable {
struct Record {
address nominator;
address delivery;
}
uint256 private registerFee;
address private treasury;
mapping (address => address) nominatorToProxy;
mapping (address => Record) proxyToRecord;
/**
* @dev Constructor initialises the register fee and treasury address:
*/
constructor(
uint256 _registerFee,
address _treasury
) {
setRegisterFee(_registerFee);
setTreasuryAddress(_treasury);
}
/**
* @dev Nominators can nominate ONCE only
*/
modifier isNotCurrentNominator(address _nominator) {
require(!nominationExists(_nominator), "Address has an existing nomination");
_;
}
/**
* @dev Check if this nominator is already on the registry
*/
modifier isExistingNominator(address _nominator) {
require(nominationExists(_nominator), "Nominator entry does not exist");
_;
}
/**
* @dev Proxys can act as proxy ONCE only
*/
modifier isNotCurrentProxy(address _proxy) {
require(!proxyRecordExists(_proxy), "Address is already acting as a proxy");
_;
}
/**
* @dev Check if this proxy is already on the registry
*/
modifier isExistingProxy(address _proxy) {
require(proxyRecordExists(_proxy), "Proxy entry does not exist");
_;
}
/**
* @dev Return if an entry exists for this nominator address
*/
function nominationExists(address _nominator) public view returns (bool) {
return nominatorToProxy[_nominator] != address(0);
}
/**
* @dev Return if an entry exists for this nominator address - For Caller
*/
function nominationExistsForCaller() public view returns (bool) {
return nominationExists(msg.sender);
}
/**
* @dev Return if an entry exists for this proxy address
*/
function proxyRecordExists(address _proxy) public view returns (bool) {
return proxyToRecord[_proxy].nominator != address(0);
}
/**
* @dev Return if an entry exists for this proxy address - For Caller
*/
function proxyRecordExistsForCaller() external view returns (bool) {
return proxyRecordExists(msg.sender);
}
/**
* @dev Return if an entry exists for this nominator address
*/
function nominatorRecordExists(address _nominator) public view returns (bool) {
return proxyToRecord[nominatorToProxy[_nominator]].nominator != address(0);
}
/**
* @dev Return if an entry exists for this nominator address - For Caller
*/
function nominatorRecordExistsForCaller() external view returns (bool) {
return nominatorRecordExists(msg.sender);
}
/**
* @dev Return if the address is an active proxy address OR a nominator with an active proxy
*/
function addressIsActive(address _receivedAddress) public view returns (bool) {
bool isActive = false;
// Check if the address is an active proxy address or active nominator:
if (proxyRecordExists(_receivedAddress) || nominatorRecordExists(_receivedAddress)){
isActive = true;
}
return isActive;
}
/**
* @dev Return if the address is an active proxy address OR a nominator with an active proxy - For Caller
*/
function addressIsActiveForCaller() external view returns (bool) {
return addressIsActive(msg.sender);
}
/**
* @dev Get entry details by proxy
*/
function getProxyRecord(address _proxy) public view returns (address nominator, address proxy, address delivery) {
Record memory currentItem = proxyToRecord[_proxy];
return (currentItem.nominator, nominatorToProxy[currentItem.nominator], currentItem.delivery);
}
/**
* @dev Get entry details by proxy - For Caller
*/
function getProxyRecordForCaller() external view returns (address nominator, address proxy, address delivery) {
return (getProxyRecord(msg.sender));
}
/**
* @dev Get entry details by nominator
*/
function getNominatorRecord(address _nominator) public view returns (address nominator, address proxy, address delivery) {
address proxyAddress = nominatorToProxy[_nominator];
if (proxyToRecord[proxyAddress].nominator == address(0)) {
// This function returns registry entries. If there is no entry on the registry (despite there being a nomination), do
// not return the proxy address:
proxyAddress = address(0);
}
return (proxyToRecord[proxyAddress].nominator, proxyAddress, proxyToRecord[proxyAddress].delivery);
}
/**
* @dev Get entry details by nominator - For Caller
*/
function getNominatorRecordForCaller() external view returns (address nominator, address proxy, address delivery) {
return (getNominatorRecord(msg.sender));
}
/**
* @dev Get nomination details only for nominator
*/
function getNomination(address _nominator) public view returns (address proxy) {
return (nominatorToProxy[_nominator]);
}
/**
* @dev Get nomination details only for nominator - For Caller
*/
function getNominationForCaller() public view returns (address proxy) {
return (getNomination(msg.sender));
}
/**
* @dev Returns the proxied address details (nominator and delivery address) for a passed proxy address
*/
function getAddresses(address _receivedAddress) public view returns (address nominator, address delivery, bool isProxied) {
require(!nominationExists(_receivedAddress), "Nominator address cannot interact directly, only through the proxy address");
Record memory currentItem = proxyToRecord[_receivedAddress];
if (proxyToRecord[_receivedAddress].nominator == address(0)) {
return(_receivedAddress, _receivedAddress, false);
}
else {
return (currentItem.nominator, currentItem.delivery, true);
}
}
/**
* @dev Returns the proxied address details (owner and delivery address) for the msg.sender being interacted with
*/
function getAddressesForCaller() external view returns (address nominator, address delivery, bool isProxied) {
return (getAddresses(msg.sender));
}
/**
* @dev Returns the current role of a given address (nominator, proxy, none)
*/
function getRole(address _roleAddress) public view returns (string memory currentRole) {
if (proxyRecordExists(_roleAddress)) {
return "Proxy";
}
if (nominationExists(_roleAddress)) {
if (proxyRecordExists(nominatorToProxy[_roleAddress])) {
return "Nominator - Proxy Active";
}
else {
return "Nominator - Proxy Pending";
}
}
return "None";
}
/**
* @dev Returns the current role of a given address (nominator, proxy, none) - For Caller
*/
function getRoleForCaller() external view returns (string memory currentRole) {
return getRole(msg.sender);
}
/**
* @dev The nominator initiates a proxy entry
*/
function makeNomination(address _proxy, uint256 _provider) external payable isNotCurrentNominator(msg.sender) isNotCurrentProxy(_proxy) isNotCurrentProxy(msg.sender) {
require (_proxy != address(0), "Proxy address must be provided");
require (_proxy != msg.sender, "Proxy address cannot be the same as Nominator address");
require(msg.value == registerFee, "Register fee must be paid");
nominatorToProxy[msg.sender] = _proxy;
emit NominationMade(msg.sender, _proxy, block.timestamp, _provider);
}
/**
* @dev Proxy accepts nomination
*/
function acceptNomination(address _nominator, address _delivery, uint256 _provider) external isNotCurrentProxy(msg.sender) isNotCurrentProxy(_nominator) {
// The nominator must be passed in:
require (_nominator != address(0), "Nominator address must be provided");
// The sender must match the proxy nomination:
require (nominatorToProxy[_nominator] == msg.sender, "Caller is not the nominated proxy for this nominator");
// We have a valid nomination, create the ProxyRegisterItem:
proxyToRecord[msg.sender] = Record(_nominator, _delivery);
emit NominationAccepted(_nominator, msg.sender, _delivery, block.timestamp, _provider);
}
/**
* @dev Change delivery address on an existing proxy item. Can only be called by the proxy address.
*/
function updateDeliveryAddress(address _delivery, uint256 _provider) external isExistingProxy(msg.sender) {
Record memory priorItem = proxyToRecord[msg.sender];
proxyToRecord[msg.sender].delivery = _delivery;
emit DeliveryUpdated(priorItem.nominator, msg.sender, _delivery, priorItem.delivery, block.timestamp, _provider);
}
/**
* @dev delete a proxy entry. BOTH the nominator and proxy can delete a proxy arrangement and all
* aspects of that proxy arrangement will be removed.
*/
function deleteRecordByNominator(uint256 _provider) external isExistingNominator(msg.sender) {
deleteProxyRegisterItems(msg.sender, nominatorToProxy[msg.sender], "nominator", _provider);
}
/**
* @dev delete a proxy entry. BOTH the nominator and proxy can delete a proxy arrangement and all
* aspects of that proxy arrangement will be removed.
*/
function deleteRecordByProxy(uint256 _provider) external isExistingProxy(msg.sender) {
deleteProxyRegisterItems(proxyToRecord[msg.sender].nominator, msg.sender, "proxy", _provider);
}
/**
* @dev delete the nomination and record (if present)
*/
function deleteProxyRegisterItems(address _nominator, address _proxy, string memory _initiator, uint256 _provider) internal {
// First remove the nomination. We know this must exists, as it has to come before the proxy can be accepted:
delete nominatorToProxy[_nominator];
emit NominationDeleted(_initiator, _nominator, _proxy, block.timestamp, _provider);
// Now remove the proxy register item. If the nominator is deleting a nomination that has not been accepted by a proxy
// then this will not exists. Check that the proxy is for this nominator.
if (proxyToRecord[_proxy].nominator == _nominator) {
address deletedDelivery = proxyToRecord[_proxy].delivery;
delete proxyToRecord[_proxy];
emit RecordDeleted(_initiator, _nominator, _proxy, deletedDelivery, block.timestamp, _provider);
}
}
/**
* @dev set the fee for initiating a registration (accepting a proxy, updating the delivery address and deletions will always be free)
*/
function setRegisterFee(uint256 _registerFee) public onlyOwner returns (bool)
{
require(_registerFee != registerFee, "No change to register fee");
registerFee = _registerFee;
emit RegisterFeeSet(registerFee);
return true;
}
/**
* @dev return the register fee:
*/
function getRegisterFee() external view returns (uint256 _registerFee) {
return(registerFee);
}
/**
* @dev set the treasury address:
*/
function setTreasuryAddress(address _treasuryAddress) public onlyOwner returns (bool)
{
require(_treasuryAddress != treasury, "No change to treasury address");
treasury = _treasuryAddress;
emit TreasuryAddressSet(treasury);
return true;
}
/**
* @dev get the treasury address:
*/
function getTreasuryAddress() external view returns (address _treasuryAddress) {
return(treasury);
}
/**
* @dev withdraw eth to the treasury:
*/
function withdraw(uint256 _amount) external onlyOwner returns (bool) {
(bool success, ) = treasury.call{value: _amount}("");
require(success, "Withdrawal failed.");
emit Withdrawal(_amount, block.timestamp);
return true;
}
/**
* @dev revert fallback
*/
fallback() external payable {
revert();
}
/**
* @dev revert receive
*/
receive() external payable {
revert();
}
}