forked from DecentralizedClimateFoundation/DCIPs
348 lines
12 KiB
Solidity
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();
|
||
|
}
|
||
|
}
|