Address Details
contract
proxy

0xa7581d8E26007f4D2374507736327f5b46Dd6bA8

Contract Name
RomulusDelegator
Creator
0x60483a–b00fa2 at 0x9b0bd4–a952b1
Implementation
RomulusDelegate | 0xe3f338ad2c06ebfd68a3b6fa7216791bd3f4d67f
Balance
0 CELO ( )
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
149 Transactions
Transfers
7 Transfers
Gas Used
15,391,827
Last Balance Update
24925794
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
RomulusDelegator




Optimization enabled
true
Compiler version
v0.8.3+commit.8d00100c




Optimization runs
200
EVM Version
istanbul




Verified at
2021-08-10T18:35:57.728606Z

Contract source code

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@poofcash/poof-token/contracts/NomResolve.sol";
import "./RomulusInterfaces.sol";

contract RomulusDelegator is RomulusDelegatorStorage, RomulusEvents, NomResolve {
  constructor(
    bytes32 timelock_,
    address token_,
    address releaseToken_,
    bytes32 admin_,
    address implementation_,
    uint votingPeriod_,
    uint votingDelay_,
    uint proposalThreshold_
  ) {
    // Admin set to msg.sender for initialization
    admin = msg.sender;

    delegateTo(
      implementation_, 
      abi.encodeWithSignature(
        "initialize(address,address,address,uint256,uint256,uint256)",
         resolve(timelock_),
         token_,
         releaseToken_,
         votingPeriod_,
         votingDelay_,
         proposalThreshold_
      )
    );
    _setImplementation(implementation_);
    admin = resolve(admin_);
	}


	/**
   * @notice Called by the admin to update the implementation of the delegator
   * @param implementation_ The address of the new implementation for delegation
   */
  function _setImplementation(address implementation_) public {
    require(msg.sender == admin, "RomulusDelegator::_setImplementation: admin only");
    require(implementation_ != address(0), "RomulusDelegator::_setImplementation: invalid implementation address");

    address oldImplementation = implementation;
    implementation = implementation_;

    emit NewImplementation(oldImplementation, implementation);
  } 

  /**
   * @notice Internal method to delegate execution to another contract
   * @dev It returns to the external caller whatever the implementation returns or forwards reverts
   * @param callee The contract to delegatecall
   * @param data The raw data to delegatecall
   */
  function delegateTo(address callee, bytes memory data) internal {
    (bool success, bytes memory returnData) = callee.delegatecall(data);
    assembly {
      if eq(success, 0) {
          revert(add(returnData, 0x20), returndatasize())
      }
    }
  }

	/**
   * @dev Delegates execution to an implementation contract.
   * It returns to the external caller whatever the implementation returns
   * or forwards reverts.
   */
  fallback () external {
    // delegate all other functions to current implementation
    (bool success, ) = implementation.delegatecall(msg.data);

    assembly {
      let free_mem_ptr := mload(0x40)
      returndatacopy(free_mem_ptr, 0, returndatasize())

      switch success
      case 0 { revert(free_mem_ptr, returndatasize()) }
      default { return(free_mem_ptr, returndatasize()) }
    }
  }
}
        

INom.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// NOTE: Name == Nom in the documentation and is used interchangeably
interface INom {
  // @dev Reserve a Nom for a duration of time
  // @param name The name to reserve
  // @param durationToReserve The length of time in seconds to reserve this name
  function reserve(bytes32 name, uint256 durationToReserve) external;

  // @dev Extend a Nom reservation
  // @param name The name to extend the reservation of
  // @param durationToExtend The length of time in seconds to extend
  function extend(bytes32 name, uint256 durationToExtend) external;

  // @dev Retrieve the address that a Nom points to
  // @param name The name to resolve
  // @returns resolution The address that the Nom points to
  function resolve(bytes32 name) external view returns (address resolution);

  // @dev Get the expiration timestamp of a Nom 
  // @param name The name to get the expiration of
  // @returns expiration Time in seconds from epoch that this Nom expires
  function expirations(bytes32 name) external view returns (uint256 expiration);

  // @dev Change the resolution of a Nom
  // @param name The name to change the resolution of
  // @param newResolution The new address that should be pointed to
  function changeResolution(bytes32 name, address newResolution) external;

  // @dev Retrieve the owner of a Nom
  // @param name The name to find the owner of
  // @returns owner The address that owns the Nom
  function nameOwner(bytes32 name) external view returns (address owner);

  // @dev Change the owner of a Nom
  // @param name The name to change the owner of
  // @param newOwner The new owner
  function changeNameOwner(bytes32 name, address newOwner) external;

  // @dev Check whether a Nom is expired
  // @param name The name to check the expiration of
  // @param expired Flag indicating whether this Nom is expired
  function isExpired(bytes32 name) external view returns (bool expired);
}

          

NomResolve.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@nomspace/nomspace/contracts/interfaces/INom.sol";

contract NomResolve {
  function resolve(bytes32 name) public view virtual returns (address) {
    INom nom = INom(
      computeChainId() == 42220 ? 0xABf8faBbC071F320F222A526A2e1fBE26429344d : 0x36C976Da6A6499Cad683064F849afa69CD4dec2e
    );
    return nom.resolve(name);
  }

  function computeChainId() internal view returns (uint256) {
    uint256 chainId;
    assembly {
      chainId := chainid()
    }
    return chainId;
  }
}
          

IHasVotes.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.3;

/**
 * Reads the votes that an account has.
 */
interface IHasVotes {
    /**
     * @notice Gets the current votes balance for `account`
     * @param account The address to get votes balance
     * @return The number of current votes for `account`
     */
    function getCurrentVotes(address account) external view returns (uint96);

    /**
     * @notice Determine the prior number of votes for an account as of a block number
     * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
     * @param account The address of the account to check
     * @param blockNumber The block number to get the vote balance at
     * @return The number of votes the account had as of the given block
     */
    function getPriorVotes(address account, uint256 blockNumber)
        external
        view
        returns (uint96);
}
          

RomulusInterfaces.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@ubeswap/governance/contracts/interfaces/IHasVotes.sol";

contract RomulusEvents {
  /// @notice An event emitted when a new proposal is created
  event ProposalCreated(
    uint256 id,
    address proposer,
    address[] targets,
    uint256[] values,
    string[] signatures,
    bytes[] calldatas,
    uint256 startBlock,
    uint256 endBlock,
    string description
  );

  /// @notice An event emitted when a vote has been cast on a proposal
  /// @param voter The address which casted a vote
  /// @param proposalId The proposal id which was voted on
  /// @param support Support value for the vote. 0=against, 1=for, 2=abstain
  /// @param votes Number of votes which were cast by the voter
  /// @param reason The reason given for the vote by the voter
  event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 votes, string reason);

  /// @notice An event emitted when a proposal has been canceled
  event ProposalCanceled(uint256 id);

  /// @notice An event emitted when a proposal has been queued in the Timelock
  event ProposalQueued(uint256 id, uint256 eta);

  /// @notice An event emitted when a proposal has been executed in the Timelock
  event ProposalExecuted(uint256 id);

  /// @notice An event emitted when the voting delay is set
  event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay);

  /// @notice An event emitted when the voting period is set
  event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod);

  /// @notice Emitted when implementation is changed
  event NewImplementation(address oldImplementation, address newImplementation);

  /// @notice Emitted when proposal threshold is set
  event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold);

  /// @notice Emitted when pendingAdmin is changed
  event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);

  /// @notice Emitted when pendingAdmin is accepted, which means admin is updated
  event NewAdmin(address oldAdmin, address newAdmin);
}

contract RomulusDelegatorStorage {
  /// @notice Administrator for this contract
  address public admin;

  /// @notice Pending administrator for this contract
  address public pendingAdmin;

  /// @notice Active brains of Governor
  address public implementation;
}

/**
 * @title Storage for Governor Bravo Delegate
 * @notice For future upgrades, do not change RomulusDelegateStorageV1. Create a new
 * contract which implements RomulusDelegateStorageV1 and following the naming convention
 * RomulusDelegateStorageVX.
 */
contract RomulusDelegateStorageV1 is RomulusDelegatorStorage {
  /// @notice The delay before voting on a proposal may take place, once proposed, in blocks
  uint256 public votingDelay;

  /// @notice The duration of voting on a proposal, in blocks
  uint256 public votingPeriod;

  /// @notice The number of votes required in order for a voter to become a proposer
  uint256 public proposalThreshold;

  /// @notice The total number of proposals
  uint256 public proposalCount;

  /// @notice The address of the Governance Timelock
  TimelockInterface public timelock;

  /// @notice The address of the governance token
  IHasVotes public token;

  /// @notice The address of the "Release" governance token
  IHasVotes public releaseToken;

  /// @notice The official record of all proposals ever proposed
  mapping(uint256 => Proposal) public proposals;
  /// @notice The official each proposal's targets:
  /// An ordered list of target addresses for calls to be made
  mapping(uint256 => address[]) public proposalTargets;
  /// @notice The official each proposal's values:
  /// An ordered list of values (i.e. msg.value) to be passed to the calls to be made
  mapping(uint256 => uint256[]) public proposalValues;
  /// @notice The official each proposal's signatures:
  /// An ordered list of function signatures to be called
  mapping(uint256 => string[]) public proposalSignatures;
  /// @notice The official each proposal's calldatas:
  /// An ordered list of calldata to be passed to each call
  mapping(uint256 => bytes[]) public proposalCalldatas;
  /// @notice The official each proposal's receipts:
  /// Receipts of ballots for the entire set of voters
  mapping(uint256 => mapping(address => Receipt)) public proposalReceipts;

  /// @notice The latest proposal for each proposer
  mapping(address => uint256) public latestProposalIds;

  struct Proposal {
    // Unique id for looking up a proposal
    uint256 id;
    // Creator of the proposal
    address proposer;
    // The timestamp that the proposal will be available for execution, set once the vote succeeds
    uint256 eta;
    // The block at which voting begins: holders must delegate their votes prior to this block
    uint256 startBlock;
    // The block at which voting ends: votes must be cast prior to this block
    uint256 endBlock;
    // Current number of votes in favor of this proposal
    uint256 forVotes;
    // Current number of votes in opposition to this proposal
    uint256 againstVotes;
    // Current number of votes for abstaining for this proposal
    uint256 abstainVotes;
    // Flag marking whether the proposal has been canceled
    bool canceled;
    // Flag marking whether the proposal has been executed
    bool executed;
  }

  /// @notice Ballot receipt record for a voter
  struct Receipt {
    // Whether or not a vote has been cast
    bool hasVoted;
    // Whether or not the voter supports the proposal or abstains
    uint8 support;
    // The number of votes the voter had, which were cast
    uint96 votes;
  }

  /// @notice Possible states that a proposal may be in
  enum ProposalState { Pending, Active, Canceled, Defeated, Succeeded, Queued, Expired, Executed }
}

interface TimelockInterface {
  function admin() external view returns (address);

  function delay() external view returns (uint256);

  function GRACE_PERIOD() external view returns (uint256);

  function acceptAdmin() external;

  function queuedTransactions(bytes32 hash) external view returns (bool);

  function queueTransaction(
    address target,
    uint256 value,
    string calldata signature,
    bytes calldata data,
    uint256 eta
  ) external returns (bytes32);

  function cancelTransaction(
    address target,
    uint256 value,
    string calldata signature,
    bytes calldata data,
    uint256 eta
  ) external;

  function executeTransaction(
    address target,
    uint256 value,
    string calldata signature,
    bytes calldata data,
    uint256 eta
  ) external payable returns (bytes memory);
}
          

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"bytes32","name":"timelock_","internalType":"bytes32"},{"type":"address","name":"token_","internalType":"address"},{"type":"address","name":"releaseToken_","internalType":"address"},{"type":"bytes32","name":"admin_","internalType":"bytes32"},{"type":"address","name":"implementation_","internalType":"address"},{"type":"uint256","name":"votingPeriod_","internalType":"uint256"},{"type":"uint256","name":"votingDelay_","internalType":"uint256"},{"type":"uint256","name":"proposalThreshold_","internalType":"uint256"}]},{"type":"event","name":"NewAdmin","inputs":[{"type":"address","name":"oldAdmin","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"NewImplementation","inputs":[{"type":"address","name":"oldImplementation","internalType":"address","indexed":false},{"type":"address","name":"newImplementation","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"NewPendingAdmin","inputs":[{"type":"address","name":"oldPendingAdmin","internalType":"address","indexed":false},{"type":"address","name":"newPendingAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ProposalCanceled","inputs":[{"type":"uint256","name":"id","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ProposalCreated","inputs":[{"type":"uint256","name":"id","internalType":"uint256","indexed":false},{"type":"address","name":"proposer","internalType":"address","indexed":false},{"type":"address[]","name":"targets","internalType":"address[]","indexed":false},{"type":"uint256[]","name":"values","internalType":"uint256[]","indexed":false},{"type":"string[]","name":"signatures","internalType":"string[]","indexed":false},{"type":"bytes[]","name":"calldatas","internalType":"bytes[]","indexed":false},{"type":"uint256","name":"startBlock","internalType":"uint256","indexed":false},{"type":"uint256","name":"endBlock","internalType":"uint256","indexed":false},{"type":"string","name":"description","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"ProposalExecuted","inputs":[{"type":"uint256","name":"id","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ProposalQueued","inputs":[{"type":"uint256","name":"id","internalType":"uint256","indexed":false},{"type":"uint256","name":"eta","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ProposalThresholdSet","inputs":[{"type":"uint256","name":"oldProposalThreshold","internalType":"uint256","indexed":false},{"type":"uint256","name":"newProposalThreshold","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"VoteCast","inputs":[{"type":"address","name":"voter","internalType":"address","indexed":true},{"type":"uint256","name":"proposalId","internalType":"uint256","indexed":false},{"type":"uint8","name":"support","internalType":"uint8","indexed":false},{"type":"uint256","name":"votes","internalType":"uint256","indexed":false},{"type":"string","name":"reason","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"VotingDelaySet","inputs":[{"type":"uint256","name":"oldVotingDelay","internalType":"uint256","indexed":false},{"type":"uint256","name":"newVotingDelay","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"VotingPeriodSet","inputs":[{"type":"uint256","name":"oldVotingPeriod","internalType":"uint256","indexed":false},{"type":"uint256","name":"newVotingPeriod","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"nonpayable"},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"_setImplementation","inputs":[{"type":"address","name":"implementation_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"admin","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"implementation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pendingAdmin","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"resolve","inputs":[{"type":"bytes32","name":"name","internalType":"bytes32"}]}]
              

Contract Creation Code

0x608060405234801561001057600080fd5b506040516108a23803806108a283398101604081905261002f916103a9565b600080546001600160a01b031916331790556100bc8461004e8a6100fc565b6040516001600160a01b039182166024820152818b16604482015290891660648201526084810186905260a4810185905260c4810184905260e40160408051601f198184030181529190526020810180516001600160e01b039081166339466de560e11b179091526101bc16565b6100c584610232565b6100ce856100fc565b600080546001600160a01b0319166001600160a01b0392909216919091179055506104559650505050505050565b6000804661a4ec14610122577336c976da6a6499cad683064f849afa69cd4dec2e610138565b73abf8fabbc071f320f222a526a2e1fbe26429344d5b604051635c23bdf560e01b8152600481018590529091506001600160a01b03821690635c23bdf59060240160206040518083038186803b15801561017b57600080fd5b505afa15801561018f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101b39190610388565b9150505b919050565b600080836001600160a01b0316836040516101d7919061041c565b600060405180830381855af49150503d8060008114610212576040519150601f19603f3d011682016040523d82523d6000602084013e610217565b606091505b5091509150600082141561022c573d60208201fd5b50505050565b6000546001600160a01b031633146102985760405162461bcd60e51b8152602060048201526030602482015260008051602061088283398151915260448201526f74696f6e3a2061646d696e206f6e6c7960801b60648201526084015b60405180910390fd5b6001600160a01b0381166103105760405162461bcd60e51b815260206004820152604460248201819052600080516020610882833981519152908201527f74696f6e3a20696e76616c696420696d706c656d656e746174696f6e206164646064820152637265737360e01b608482015260a40161028f565b600280546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a910160405180910390a15050565b80516001600160a01b03811681146101b757600080fd5b600060208284031215610399578081fd5b6103a282610371565b9392505050565b600080600080600080600080610100898b0312156103c5578384fd5b885197506103d560208a01610371565b96506103e360408a01610371565b9550606089015194506103f860808a01610371565b935060a0890151925060c0890151915060e089015190509295985092959890939650565b60008251815b8181101561043c5760208186018101518583015201610422565b8181111561044a5782828501525b509190910192915050565b61041e806104646000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806326782247146100d25780635c23bdf5146101015780635c60da1b14610114578063bb913f4114610127578063f851a4401461013c575b6002546040516000916001600160a01b03169061007790839036906103c0565b600060405180830381855af49150503d80600081146100b2576040519150601f19603f3d011682016040523d82523d6000602084013e6100b7565b606091505b505090506040513d6000823e8180156100ce573d82f35b3d82fd5b6001546100e5906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b6100e561010f3660046103a8565b61014f565b6002546100e5906001600160a01b031681565b61013a610135366004610370565b61020d565b005b6000546100e5906001600160a01b031681565b6000804661a4ec14610175577336c976da6a6499cad683064f849afa69cd4dec2e61018b565b73abf8fabbc071f320f222a526a2e1fbe26429344d5b604051635c23bdf560e01b8152600481018590529091506001600160a01b03821690635c23bdf59060240160206040518083038186803b1580156101ce57600080fd5b505afa1580156101e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610206919061038c565b9392505050565b6000546001600160a01b031633146102855760405162461bcd60e51b815260206004820152603060248201527f526f6d756c757344656c656761746f723a3a5f736574496d706c656d656e746160448201526f74696f6e3a2061646d696e206f6e6c7960801b60648201526084015b60405180910390fd5b6001600160a01b03811661030f5760405162461bcd60e51b8152602060048201526044602482018190527f526f6d756c757344656c656761746f723a3a5f736574496d706c656d656e7461908201527f74696f6e3a20696e76616c696420696d706c656d656e746174696f6e206164646064820152637265737360e01b608482015260a40161027c565b600280546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a910160405180910390a15050565b600060208284031215610381578081fd5b8135610206816103d0565b60006020828403121561039d578081fd5b8151610206816103d0565b6000602082840312156103b9578081fd5b5035919050565b6000828483379101908152919050565b6001600160a01b03811681146103e557600080fd5b5056fea2646970667358221220dfc9f0a36ca3a90a4fc9ea774517f91916d5386b1ec07a4fde21604cd497492c64736f6c63430008030033526f6d756c757344656c656761746f723a3a5f736574496d706c656d656e7461556265476f7654696d656c6f636b00000000000000000000000000000000000000000000000000000000000000be915b9dcf56a3cbe739d9b9c202ca692409ec0000000000000000000000005ed248077bd07ee9b530f7c40be0c1dae4c131c0556265476f7654696d656c6f636b000000000000000000000000000000000000000000000000000000000000e3f338ad2c06ebfd68a3b6fa7216791bd3f4d67f000000000000000000000000000000000000000000000000000000000001d88000000000000000000000000000000000000000000000000000000000000043800000000000000000000000000000000000000000000069e10de76676d0800000

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100575760003560e01c806326782247146100d25780635c23bdf5146101015780635c60da1b14610114578063bb913f4114610127578063f851a4401461013c575b6002546040516000916001600160a01b03169061007790839036906103c0565b600060405180830381855af49150503d80600081146100b2576040519150601f19603f3d011682016040523d82523d6000602084013e6100b7565b606091505b505090506040513d6000823e8180156100ce573d82f35b3d82fd5b6001546100e5906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b6100e561010f3660046103a8565b61014f565b6002546100e5906001600160a01b031681565b61013a610135366004610370565b61020d565b005b6000546100e5906001600160a01b031681565b6000804661a4ec14610175577336c976da6a6499cad683064f849afa69cd4dec2e61018b565b73abf8fabbc071f320f222a526a2e1fbe26429344d5b604051635c23bdf560e01b8152600481018590529091506001600160a01b03821690635c23bdf59060240160206040518083038186803b1580156101ce57600080fd5b505afa1580156101e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610206919061038c565b9392505050565b6000546001600160a01b031633146102855760405162461bcd60e51b815260206004820152603060248201527f526f6d756c757344656c656761746f723a3a5f736574496d706c656d656e746160448201526f74696f6e3a2061646d696e206f6e6c7960801b60648201526084015b60405180910390fd5b6001600160a01b03811661030f5760405162461bcd60e51b8152602060048201526044602482018190527f526f6d756c757344656c656761746f723a3a5f736574496d706c656d656e7461908201527f74696f6e3a20696e76616c696420696d706c656d656e746174696f6e206164646064820152637265737360e01b608482015260a40161027c565b600280546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a910160405180910390a15050565b600060208284031215610381578081fd5b8135610206816103d0565b60006020828403121561039d578081fd5b8151610206816103d0565b6000602082840312156103b9578081fd5b5035919050565b6000828483379101908152919050565b6001600160a01b03811681146103e557600080fd5b5056fea2646970667358221220dfc9f0a36ca3a90a4fc9ea774517f91916d5386b1ec07a4fde21604cd497492c64736f6c63430008030033