账户
0xde...0905
0xDE...0905

0xDE...0905

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.8.17+commit.8df45f5f
语言
Solidity
合同源代码
文件 1 的 1:DelegateRegistry.sol
/**
 *Submitted for verification at gnosisscan.io on 2023-02-14
*/

// SPDX-License-Identifier: LGPL-3.0-only
/*

  ____       _                  _       
 |  _ \  ___| | ___  __ _  __ _| |_ ___ 
 | | | |/ _ \ |/ _ \/ _` |/ _` | __/ _ \
 | |_| |  __/ |  __/ (_| | (_| | ||  __/
 |____/ \___|_|\___|\__, |\__,_|\__\___|
  ____            _ |___/               
 |  _ \ ___  __ _(_)___| |_ _ __ _   _  
 | |_) / _ \/ _` | / __| __| '__| | | | 
 |  _ <  __/ (_| | \__ \ |_| |  | |_| | 
 |_| \_\___|\__, |_|___/\__|_|   \__, | 
            |___/                |___/  

 Made with ❤️ by Gnosis Guild
*/
pragma solidity ^0.8.17;

struct Delegation {
    bytes32 delegate;
    uint256 ratio;
}

contract DelegateRegistry {
    // Mapping from account address => context => array of user-defined delegations.
    mapping(address => mapping(string => Delegation[])) private delegations;
    // Mapping from account address => context => user-defined delegation expiration dates.
    mapping(address => mapping(string => uint256)) private expirationTimestamps;
    // Mapping from delegate address => context => opt-out status
    mapping(address => mapping(string => bool)) public optouts;

    event ExpirationUpdated(
        address indexed account,
        string context,
        Delegation[] delegation,
        uint256 expirationTimestamp
    );
    event DelegationUpdated(
        address indexed account,
        string context,
        Delegation[] previousDelegation,
        Delegation[] delegation,
        uint256 expirationTimestamp
    );
    event DelegationCleared(
        address indexed account,
        string context,
        Delegation[] delegatesCleared
    );
    event OptOutStatusSet(
        address indexed delegate,
        string context,
        bool optout
    );

    /// @dev Delegation is already set to this value.
    error DuplicateDelegation(address emitter, Delegation[] delegation);
    /// @dev Duplicate expiration timestamp.
    error DuplicateTimestamp(address emitter, uint256 expirationTimestamp);
    /// @dev Given delegate is 0 or a duplicate.
    error InvalidDelegateID(address emiter, bytes32 delegate);
    /// @dev Duplicate opt-out status
    error DuplicateOptoutStatus(address emitter, string context, bool optout);

    /// @dev Sets a delegate for the msg.sender and a specific context.
    /// @param context ID of the context in which delegation should be set.
    /// @param delegation Array of delegations. Must be sorted in numerical order, from smallest to largets.
    /// @param expirationTimestamp Unix timestamp for at which this delegation should expire.
    /// @notice setDelegation() will overrite the user's previous delegation for the given context.
    function setDelegation(
        string memory context,
        Delegation[] memory delegation,
        uint256 expirationTimestamp
    ) public {
        bytes32 currentDelegationHash = keccak256(
            abi.encode(delegations[msg.sender][context])
        );
        bytes32 delegationHash = keccak256(abi.encode(delegation));

        if (
            currentDelegationHash == delegationHash &&
            expirationTimestamps[msg.sender][context] == expirationTimestamp
        ) revert DuplicateDelegation(address(this), delegation);

        emit DelegationUpdated(
            msg.sender,
            context,
            delegations[msg.sender][context],
            delegation,
            expirationTimestamp
        );

        delete delegations[msg.sender][context];

        // Update delegation mapping
        bytes32 previous;
        for (uint i = 0; i < delegation.length; i++) {
            if (delegation[i].delegate <= previous)
                revert InvalidDelegateID(address(this), delegation[i].delegate);
            delegations[msg.sender][context].push(delegation[i]);
            previous = delegation[i].delegate;
        }

        // set delegation expiration
        expirationTimestamps[msg.sender][context] = expirationTimestamp;
    }

    /// @dev Clears msg.sender's delegation in a given context.
    /// @param context ID of the context in which delegation should be cleared.
    function clearDelegation(string memory context) public {
        emit DelegationCleared(
            msg.sender,
            context,
            delegations[msg.sender][context]
        );
        delete delegations[msg.sender][context];
        delete expirationTimestamps[msg.sender][context];
    }

    /// @dev Sets msg.senders expiration timestamp for a given context.
    /// @param context ID of the context in which the timestamp should be set.
    /// @param expirationTimestamp Unix timestamp at which the delegations in this context should expire.
    function setExpiration(
        string memory context,
        uint256 expirationTimestamp
    ) public {
        if (expirationTimestamps[msg.sender][context] == expirationTimestamp)
            revert DuplicateTimestamp(address(this), expirationTimestamp);
        expirationTimestamps[msg.sender][context] = expirationTimestamp;
        emit ExpirationUpdated(
            msg.sender,
            context,
            delegations[msg.sender][context],
            expirationTimestamp
        );
    }

    /// @dev Sets an "opt-out" status, allowing users to signal a desire to opt-out of receiving delegations.
    /// @param context Context in which the user wishes to set their opt-out status.
    /// @param _optout opt-out status.
    function optout(string memory context, bool _optout) public {
        if (optouts[msg.sender][context] == _optout)
            revert DuplicateOptoutStatus(address(this), context, _optout);
        optouts[msg.sender][context] = _optout;
        emit OptOutStatusSet(msg.sender, context, _optout);
    }

    /// @dev Returns the delegation details for a given account in a given context.
    /// @param context ID of the context to query.
    /// @param account Address of the account to query.
    /// @return delegation Array of delegations.
    /// @return expirationTimestamp Unix timestamp at which this delegation will expire.
    function getDelegation(
        string memory context,
        address account
    )
        public
        view
        returns (Delegation[] memory delegation, uint256 expirationTimestamp)
    {
        delegation = delegations[account][context];
        expirationTimestamp = expirationTimestamps[account][context];
    }
}
设置
{
  "compilationTarget": {
    "DelegateRegistry.sol": "DelegateRegistry"
  },
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"address","name":"emitter","type":"address"},{"components":[{"internalType":"bytes32","name":"delegate","type":"bytes32"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Delegation[]","name":"delegation","type":"tuple[]"}],"name":"DuplicateDelegation","type":"error"},{"inputs":[{"internalType":"address","name":"emitter","type":"address"},{"internalType":"string","name":"context","type":"string"},{"internalType":"bool","name":"optout","type":"bool"}],"name":"DuplicateOptoutStatus","type":"error"},{"inputs":[{"internalType":"address","name":"emitter","type":"address"},{"internalType":"uint256","name":"expirationTimestamp","type":"uint256"}],"name":"DuplicateTimestamp","type":"error"},{"inputs":[{"internalType":"address","name":"emiter","type":"address"},{"internalType":"bytes32","name":"delegate","type":"bytes32"}],"name":"InvalidDelegateID","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"string","name":"context","type":"string"},{"components":[{"internalType":"bytes32","name":"delegate","type":"bytes32"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"indexed":false,"internalType":"struct Delegation[]","name":"delegatesCleared","type":"tuple[]"}],"name":"DelegationCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"string","name":"context","type":"string"},{"components":[{"internalType":"bytes32","name":"delegate","type":"bytes32"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"indexed":false,"internalType":"struct Delegation[]","name":"previousDelegation","type":"tuple[]"},{"components":[{"internalType":"bytes32","name":"delegate","type":"bytes32"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"indexed":false,"internalType":"struct Delegation[]","name":"delegation","type":"tuple[]"},{"indexed":false,"internalType":"uint256","name":"expirationTimestamp","type":"uint256"}],"name":"DelegationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"string","name":"context","type":"string"},{"components":[{"internalType":"bytes32","name":"delegate","type":"bytes32"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"indexed":false,"internalType":"struct Delegation[]","name":"delegation","type":"tuple[]"},{"indexed":false,"internalType":"uint256","name":"expirationTimestamp","type":"uint256"}],"name":"ExpirationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"string","name":"context","type":"string"},{"indexed":false,"internalType":"bool","name":"optout","type":"bool"}],"name":"OptOutStatusSet","type":"event"},{"inputs":[{"internalType":"string","name":"context","type":"string"}],"name":"clearDelegation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"context","type":"string"},{"internalType":"address","name":"account","type":"address"}],"name":"getDelegation","outputs":[{"components":[{"internalType":"bytes32","name":"delegate","type":"bytes32"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Delegation[]","name":"delegation","type":"tuple[]"},{"internalType":"uint256","name":"expirationTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"context","type":"string"},{"internalType":"bool","name":"_optout","type":"bool"}],"name":"optout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"string","name":"","type":"string"}],"name":"optouts","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"context","type":"string"},{"components":[{"internalType":"bytes32","name":"delegate","type":"bytes32"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"internalType":"struct Delegation[]","name":"delegation","type":"tuple[]"},{"internalType":"uint256","name":"expirationTimestamp","type":"uint256"}],"name":"setDelegation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"context","type":"string"},{"internalType":"uint256","name":"expirationTimestamp","type":"uint256"}],"name":"setExpiration","outputs":[],"stateMutability":"nonpayable","type":"function"}]