Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 147 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Request Subscrip... | 21427180 | 3 days ago | IN | 0 ETH | 0.0015161 | ||||
Request Redempti... | 21426435 | 3 days ago | IN | 0 ETH | 0.00100712 | ||||
Request Redempti... | 21408481 | 5 days ago | IN | 0 ETH | 0.00102961 | ||||
Request Subscrip... | 21383911 | 9 days ago | IN | 0 ETH | 0.00298937 | ||||
Request Subscrip... | 21358304 | 12 days ago | IN | 0 ETH | 0.00184177 | ||||
Request Redempti... | 21309309 | 19 days ago | IN | 0 ETH | 0.00151042 | ||||
Request Subscrip... | 21297000 | 21 days ago | IN | 0 ETH | 0.00128281 | ||||
Request Subscrip... | 21286316 | 22 days ago | IN | 0 ETH | 0.00143703 | ||||
Request Subscrip... | 21281745 | 23 days ago | IN | 0 ETH | 0.00302281 | ||||
Request Subscrip... | 21279061 | 23 days ago | IN | 0 ETH | 0.00158827 | ||||
Request Subscrip... | 21274256 | 24 days ago | IN | 0 ETH | 0.00157432 | ||||
Request Redempti... | 21226656 | 31 days ago | IN | 0 ETH | 0.00090598 | ||||
Request Subscrip... | 21177064 | 37 days ago | IN | 0 ETH | 0.00287883 | ||||
Request Redempti... | 21171233 | 38 days ago | IN | 0 ETH | 0.00315227 | ||||
Request Redempti... | 21160273 | 40 days ago | IN | 0 ETH | 0.00173887 | ||||
Request Subscrip... | 21136356 | 43 days ago | IN | 0 ETH | 0.00241162 | ||||
Request Subscrip... | 21126547 | 45 days ago | IN | 0 ETH | 0.00346092 | ||||
Request Subscrip... | 21014093 | 60 days ago | IN | 0 ETH | 0.00128539 | ||||
Request Redempti... | 21001070 | 62 days ago | IN | 0 ETH | 0.00154613 | ||||
Request Subscrip... | 20993972 | 63 days ago | IN | 0 ETH | 0.00321295 | ||||
Request Redempti... | 20992840 | 63 days ago | IN | 0 ETH | 0.00319656 | ||||
Request Subscrip... | 20985803 | 64 days ago | IN | 0 ETH | 0.00496293 | ||||
Request Redempti... | 20884081 | 78 days ago | IN | 0 ETH | 0.00067864 | ||||
Request Subscrip... | 20879483 | 79 days ago | IN | 0 ETH | 0.00327148 | ||||
Request Subscrip... | 20876725 | 79 days ago | IN | 0 ETH | 0.00074556 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
USDYManager
Compiler Version
v0.8.16+commit.07a7930e
Optimization Enabled:
Yes with 100 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; import "contracts/RWAHubOffChainRedemptions.sol"; import "contracts/usdy/blocklist/BlocklistClient.sol"; import "contracts/sanctions/SanctionsListClient.sol"; import "contracts/interfaces/IUSDYManager.sol"; contract USDYManager is RWAHubOffChainRedemptions, BlocklistClient, SanctionsListClient, IUSDYManager { bytes32 public constant TIMESTAMP_SETTER_ROLE = keccak256("TIMESTAMP_SETTER_ROLE"); mapping(bytes32 => uint256) public depositIdToClaimableTimestamp; constructor( address _collateral, address _rwa, address managerAdmin, address pauser, address _assetSender, address _feeRecipient, uint256 _minimumDepositAmount, uint256 _minimumRedemptionAmount, address blocklist, address sanctionsList ) RWAHubOffChainRedemptions( _collateral, _rwa, managerAdmin, pauser, _assetSender, _feeRecipient, _minimumDepositAmount, _minimumRedemptionAmount ) BlocklistClient(blocklist) SanctionsListClient(sanctionsList) {} /** * @notice Function to enforce blocklist and sanctionslist restrictions to be * implemented on calls to `requestSubscription` and * `claimRedemption` * * @param account The account to check blocklist and sanctions list status * for */ function _checkRestrictions(address account) internal view override { if (_isBlocked(account)) { revert BlockedAccount(); } if (_isSanctioned(account)) { revert SanctionedAccount(); } } /** * @notice Internal hook that is called by `claimMint` to enforce the time * at which a user can claim their USDY * * @param depositId The depositId to check the claimable timestamp for * * @dev This function will call the `_claimMint` function in the parent * once USDY-specific checks have been made */ function _claimMint(bytes32 depositId) internal virtual override { if (depositIdToClaimableTimestamp[depositId] == 0) { revert ClaimableTimestampNotSet(); } if (depositIdToClaimableTimestamp[depositId] > block.timestamp) { revert MintNotYetClaimable(); } super._claimMint(depositId); delete depositIdToClaimableTimestamp[depositId]; } /** * @notice Update blocklist address * * @param blocklist The new blocklist address */ function setBlocklist( address blocklist ) external override onlyRole(MANAGER_ADMIN) { _setBlocklist(blocklist); } /** * @notice Update sanctions list address * * @param sanctionsList The new sanctions list address */ function setSanctionsList( address sanctionsList ) external override onlyRole(MANAGER_ADMIN) { _setSanctionsList(sanctionsList); } /** * @notice Set the claimable timestamp for a list of depositIds * * @param claimTimestamp The timestamp at which the deposit can be claimed * @param depositIds The depositIds to set the claimable timestamp for */ function setClaimableTimestamp( uint256 claimTimestamp, bytes32[] calldata depositIds ) external onlyRole(TIMESTAMP_SETTER_ROLE) { if (claimTimestamp < block.timestamp) { revert ClaimableTimestampInPast(); } uint256 depositsSize = depositIds.length; for (uint256 i; i < depositsSize; ++i) { depositIdToClaimableTimestamp[depositIds[i]] = claimTimestamp; emit ClaimableTimestampSet(claimTimestamp, depositIds[i]); } } }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; import "contracts/RWAHub.sol"; import "contracts/interfaces/IRWAHubOffChainRedemptions.sol"; abstract contract RWAHubOffChainRedemptions is RWAHub, IRWAHubOffChainRedemptions { // To enable and disable off chain redemptions bool public offChainRedemptionPaused; // Minimum off chain redemption amount uint256 public minimumOffChainRedemptionAmount; constructor( address _collateral, address _rwa, address managerAdmin, address pauser, address _assetSender, address _feeRecipient, uint256 _minimumDepositAmount, uint256 _minimumRedemptionAmount ) RWAHub( _collateral, _rwa, managerAdmin, pauser, _assetSender, _feeRecipient, _minimumDepositAmount, _minimumRedemptionAmount ) { // Default to the same minimum redemption amount as for On-Chain // redemptions. minimumOffChainRedemptionAmount = _minimumRedemptionAmount; } /** * @notice Request a redemption to be serviced off chain. * * @param amountRWATokenToRedeem The requested redemption amount * @param offChainDestination A hash of the destination to which * the request should be serviced to. */ function requestRedemptionServicedOffchain( uint256 amountRWATokenToRedeem, bytes32 offChainDestination ) external nonReentrant ifNotPaused(offChainRedemptionPaused) { if (amountRWATokenToRedeem < minimumOffChainRedemptionAmount) { revert RedemptionTooSmall(); } bytes32 redemptionId = bytes32(redemptionRequestCounter++); rwa.burnFrom(msg.sender, amountRWATokenToRedeem); emit RedemptionRequestedServicedOffChain( msg.sender, redemptionId, amountRWATokenToRedeem, offChainDestination ); } /** * @notice Function to pause off chain redemptoins */ function pauseOffChainRedemption() external onlyRole(PAUSER_ADMIN) { offChainRedemptionPaused = true; emit OffChainRedemptionPaused(msg.sender); } /** * @notice Function to unpause off chain redemptoins */ function unpauseOffChainRedemption() external onlyRole(MANAGER_ADMIN) { offChainRedemptionPaused = false; emit OffChainRedemptionUnpaused(msg.sender); } /** * @notice Admin Function to set the minimum off chain redemption amount * * @param _minimumOffChainRedemptionAmount The new minimum off chain * redemption amount */ function setOffChainRedemptionMinimum( uint256 _minimumOffChainRedemptionAmount ) external onlyRole(MANAGER_ADMIN) { uint256 oldMinimum = minimumOffChainRedemptionAmount; minimumOffChainRedemptionAmount = _minimumOffChainRedemptionAmount; emit OffChainRedemptionMinimumSet( oldMinimum, _minimumOffChainRedemptionAmount ); } }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; import "contracts/external/chainalysis/ISanctionsList.sol"; import "contracts/sanctions/ISanctionsListClient.sol"; /** * @title SanctionsListClient * @author Ondo Finance * @notice This abstract contract manages state required for clients * of the sanctions list */ abstract contract SanctionsListClient is ISanctionsListClient { // Sanctions list address ISanctionsList public override sanctionsList; /** * @notice Constructor * * @param _sanctionsList Address of the sanctions list contract */ constructor(address _sanctionsList) { _setSanctionsList(_sanctionsList); } /** * @notice Sets the sanctions list address for this client * * @param _sanctionsList The new sanctions list address */ function _setSanctionsList(address _sanctionsList) internal { if (_sanctionsList == address(0)) { revert SanctionsListZeroAddress(); } address oldSanctionsList = address(sanctionsList); sanctionsList = ISanctionsList(_sanctionsList); emit SanctionsListSet(oldSanctionsList, _sanctionsList); } /** * @notice Checks whether an address has been sanctioned * * @param account The account to check */ function _isSanctioned(address account) internal view returns (bool) { return sanctionsList.isSanctioned(account); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; import "contracts/interfaces/IBlocklist.sol"; import "contracts/interfaces/IBlocklistClient.sol"; /** * @title BlocklistClient * @author Ondo Finance * @notice This abstract contract manages state for blocklist clients */ abstract contract BlocklistClient is IBlocklistClient { // blocklist address IBlocklist public override blocklist; /** * @notice Constructor * * @param _blocklist Address of the blocklist contract */ constructor(address _blocklist) { _setBlocklist(_blocklist); } /** * @notice Sets the blocklist address for this client * * @param _blocklist The new blocklist address */ function _setBlocklist(address _blocklist) internal { if (_blocklist == address(0)) { revert BlocklistZeroAddress(); } address oldBlocklist = address(blocklist); blocklist = IBlocklist(_blocklist); emit BlocklistSet(oldBlocklist, _blocklist); } /** * @notice Checks whether an address has been blocked * * @param account The account to check */ function _isBlocked(address account) internal view returns (bool) { return blocklist.isBlocked(account); } }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; interface IUSDYManager { function setClaimableTimestamp( uint256 claimDate, bytes32[] calldata depositIds ) external; /** * @notice Event emitted when claimable timestamp is set * * @param claimTimestamp The timestamp at which the mint can be claimed * @param depositId The depositId that can claim at the given `claimTimestamp` */ event ClaimableTimestampSet( uint256 indexed claimTimestamp, bytes32 indexed depositId ); /// ERRORS /// error MintNotYetClaimable(); error ClaimableTimestampInPast(); error ClaimableTimestampNotSet(); }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; interface IRWAHubOffChainRedemptions { function requestRedemptionServicedOffchain( uint256 amountRWATokenToRedeem, bytes32 offChainDestination ) external; function pauseOffChainRedemption() external; function unpauseOffChainRedemption() external; function setOffChainRedemptionMinimum(uint256 minimumAmount) external; /** * @notice Event emitted when redemption request is submitted * * @param user The user submitting the offchain redemption request * @param redemptionId The id corresponding to a given offchain redemption request * @param rwaTokenAmountIn The amount of cash being burned * @param offChainDestination Hash of destination to which the request * should be serviced to */ event RedemptionRequestedServicedOffChain( address indexed user, bytes32 indexed redemptionId, uint256 rwaTokenAmountIn, bytes32 offChainDestination ); /** * @notice Event emitted when the off chain redemption feature is * paused * * @param caller Address which initiated the pause */ event OffChainRedemptionPaused(address caller); /** * @notice Event emitted when the off chain redemption feature is * unpaused * * @param caller Address which initiated the unpause */ event OffChainRedemptionUnpaused(address caller); /** * @notice Event emitted when the off chain redemption minimum is * updated * * @param oldMinimum the old minimum redemption amount * @param newMinimum the new minimum redemption amount */ event OffChainRedemptionMinimumSet(uint256 oldMinimum, uint256 newMinimum); }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; import "contracts/interfaces/IPricerReader.sol"; import "contracts/interfaces/IRWALike.sol"; import "contracts/external/openzeppelin/contracts/token/IERC20.sol"; import "contracts/external/openzeppelin/contracts/token/SafeERC20.sol"; import "contracts/interfaces/IRWAHub.sol"; // Additional Dependencies import "contracts/external/openzeppelin/contracts/token/IERC20Metadata.sol"; import "contracts/external/openzeppelin/contracts/access/AccessControlEnumerable.sol"; import "contracts/external/openzeppelin/contracts/security/ReentrancyGuard.sol"; abstract contract RWAHub is IRWAHub, ReentrancyGuard, AccessControlEnumerable { using SafeERC20 for IERC20; // RWA Token contract IRWALike public immutable rwa; // Pointer to Pricer IPricerReader public pricer; // Address to receive deposits address public constant assetRecipient = 0xbDa73A0F13958ee444e0782E1768aB4B76EdaE28; // USDY - CB Deposit Address // Address to send redemptions address public assetSender; // Address fee recipient address public feeRecipient; // Mapping from deposit Id -> Depositor mapping(bytes32 => Depositor) public depositIdToDepositor; // Mapping from redemptionId -> Redeemer mapping(bytes32 => Redeemer) public redemptionIdToRedeemer; /// @dev Mint/Redeem Parameters // Minimum amount that must be deposited to mint the RWA token // Denoted in decimals of `collateral` uint256 public minimumDepositAmount; // Minimum amount that must be redeemed for a withdraw request uint256 public minimumRedemptionAmount; // Minting fee specified in basis points uint256 public mintFee = 0; // Redemption fee specified in basis points uint256 public redemptionFee = 0; // The asset accepted by the RWAHub IERC20 public immutable collateral; // Decimal multiplier representing the difference between `rwa` decimals // In `collateral` token decimals uint256 public immutable decimalsMultiplier; // Deposit counter to map subscription requests to uint256 public subscriptionRequestCounter = 1; // Redemption Id to map from uint256 public redemptionRequestCounter = 1; // Helper constant that allows us to specify basis points in calculations uint256 public constant BPS_DENOMINATOR = 10_000; // Pause variables bool public redemptionPaused; bool public subscriptionPaused; /// @dev Role based access control roles bytes32 public constant MANAGER_ADMIN = keccak256("MANAGER_ADMIN"); bytes32 public constant PAUSER_ADMIN = keccak256("PAUSER_ADMIN"); bytes32 public constant PRICE_ID_SETTER_ROLE = keccak256("PRICE_ID_SETTER_ROLE"); bytes32 public constant RELAYER_ROLE = keccak256("RELAYER_ROLE"); /// @notice constructor constructor( address _collateral, address _rwa, address managerAdmin, address pauser, address _assetSender, address _feeRecipient, uint256 _minimumDepositAmount, uint256 _minimumRedemptionAmount ) { if (_collateral == address(0)) { revert CollateralCannotBeZero(); } if (_rwa == address(0)) { revert RWACannotBeZero(); } if (_assetSender == address(0)) { revert AssetSenderCannotBeZero(); } if (_feeRecipient == address(0)) { revert FeeRecipientCannotBeZero(); } _grantRole(DEFAULT_ADMIN_ROLE, managerAdmin); _grantRole(MANAGER_ADMIN, managerAdmin); _grantRole(PAUSER_ADMIN, pauser); _setRoleAdmin(PAUSER_ADMIN, MANAGER_ADMIN); _setRoleAdmin(PRICE_ID_SETTER_ROLE, MANAGER_ADMIN); _setRoleAdmin(RELAYER_ROLE, MANAGER_ADMIN); collateral = IERC20(_collateral); rwa = IRWALike(_rwa); feeRecipient = _feeRecipient; assetSender = _assetSender; minimumDepositAmount = _minimumDepositAmount; minimumRedemptionAmount = _minimumRedemptionAmount; decimalsMultiplier = 10 ** (IERC20Metadata(_rwa).decimals() - IERC20Metadata(_collateral).decimals()); } /*////////////////////////////////////////////////////////////// Subscription/Redemption Functions //////////////////////////////////////////////////////////////*/ /** * @notice Function used by users to request subscription to the fund * * @param amount The amount of collateral one wished to deposit */ function requestSubscription( uint256 amount ) external virtual nonReentrant ifNotPaused(subscriptionPaused) checkRestrictions(msg.sender) { if (amount < minimumDepositAmount) { revert DepositTooSmall(); } uint256 feesInCollateral = _getMintFees(amount); uint256 depositAmountAfterFee = amount - feesInCollateral; // Link the depositor to their deposit ID bytes32 depositId = bytes32(subscriptionRequestCounter++); depositIdToDepositor[depositId] = Depositor( msg.sender, depositAmountAfterFee, 0 ); if (feesInCollateral > 0) { collateral.safeTransferFrom(msg.sender, feeRecipient, feesInCollateral); } collateral.safeTransferFrom( msg.sender, assetRecipient, depositAmountAfterFee ); emit MintRequested( msg.sender, depositId, amount, depositAmountAfterFee, feesInCollateral ); } /** * @notice Function used to claim tokens corresponding to a deposit request * * @param depositIds An array containing the deposit Ids one wishes to claim * * @dev Implicitly does all transfer checks present in underlying `rwa` * @dev The priceId corresponding to a given depositId must be set prior to * claiming a mint */ function claimMint( bytes32[] calldata depositIds ) external virtual nonReentrant ifNotPaused(subscriptionPaused) { uint256 depositsSize = depositIds.length; for (uint256 i = 0; i < depositsSize; ++i) { _claimMint(depositIds[i]); } } /** * @notice Internal claim mint helper * * @dev This function can be overriden to implement custom claiming logic */ function _claimMint(bytes32 depositId) internal virtual { Depositor memory depositor = depositIdToDepositor[depositId]; // Revert if priceId is not set if (depositor.priceId == 0) { revert PriceIdNotSet(); } uint256 price = pricer.getPrice(depositor.priceId); uint256 rwaOwed = _getMintAmountForPrice( depositor.amountDepositedMinusFees, price ); delete depositIdToDepositor[depositId]; rwa.mint(depositor.user, rwaOwed); emit MintCompleted( depositor.user, depositId, rwaOwed, depositor.amountDepositedMinusFees, price, depositor.priceId ); } /** * @notice Function used by users to request a redemption from the fund * * @param amount The amount (in units of `rwa`) that a user wishes to redeem * from the fund */ function requestRedemption( uint256 amount ) external virtual nonReentrant ifNotPaused(redemptionPaused) { if (amount < minimumRedemptionAmount) { revert RedemptionTooSmall(); } bytes32 redemptionId = bytes32(redemptionRequestCounter++); redemptionIdToRedeemer[redemptionId] = Redeemer(msg.sender, amount, 0); rwa.burnFrom(msg.sender, amount); emit RedemptionRequested(msg.sender, redemptionId, amount); } /** * @notice Function to claim collateral corresponding to a redemption request * * @param redemptionIds an Array of redemption Id's which ought to fulfilled * * @dev Implicitly does all checks present in underlying `rwa` * @dev The price Id corresponding to a redemptionId must be set prior to * claiming a redemption */ function claimRedemption( bytes32[] calldata redemptionIds ) external virtual nonReentrant ifNotPaused(redemptionPaused) { uint256 fees; uint256 redemptionsSize = redemptionIds.length; for (uint256 i = 0; i < redemptionsSize; ++i) { Redeemer memory member = redemptionIdToRedeemer[redemptionIds[i]]; _checkRestrictions(member.user); if (member.priceId == 0) { // Then the price for this redemption has not been set revert PriceIdNotSet(); } // Calculate collateral due and fees uint256 price = pricer.getPrice(member.priceId); uint256 collateralDue = _getRedemptionAmountForRwa( member.amountRwaTokenBurned, price ); uint256 fee = _getRedemptionFees(collateralDue); uint256 collateralDuePostFees = collateralDue - fee; fees += fee; delete redemptionIdToRedeemer[redemptionIds[i]]; collateral.safeTransferFrom( assetSender, member.user, collateralDuePostFees ); emit RedemptionCompleted( member.user, redemptionIds[i], member.amountRwaTokenBurned, collateralDuePostFees, price ); } if (fees > 0) { collateral.safeTransferFrom(assetSender, feeRecipient, fees); } } /*////////////////////////////////////////////////////////////// Relayer Functions //////////////////////////////////////////////////////////////*/ /** * @notice Adds a deposit proof to the contract * * @param txHash The transaction hash of the deposit * @param user The address of the user who made the deposit * @param depositAmountAfterFee The amount of the deposit after fees * @param feeAmount The amount of the fees taken * @param timestamp The timestamp of the deposit * * @dev txHash is used as the depositId in storage * @dev All amounts are in decimals of `collateral` */ function addProof( bytes32 txHash, address user, uint256 depositAmountAfterFee, uint256 feeAmount, uint256 timestamp ) external override onlyRole(RELAYER_ROLE) checkRestrictions(user) { if (depositIdToDepositor[txHash].user != address(0)) { revert DepositProofAlreadyExists(); } depositIdToDepositor[txHash] = Depositor(user, depositAmountAfterFee, 0); emit DepositProofAdded( txHash, user, depositAmountAfterFee, feeAmount, timestamp ); } /*////////////////////////////////////////////////////////////// PriceId Setters //////////////////////////////////////////////////////////////*/ /** * @notice Admin function to associate a depositId with a given Price Id * * @param depositIds an Array of deposit Ids to be associated * @param priceIds an Array of price Ids to be associated * * @dev Array size must match */ function setPriceIdForDeposits( bytes32[] calldata depositIds, uint256[] calldata priceIds ) external virtual onlyRole(PRICE_ID_SETTER_ROLE) { uint256 depositsSize = depositIds.length; if (depositsSize != priceIds.length) { revert ArraySizeMismatch(); } for (uint256 i = 0; i < depositsSize; ++i) { if (depositIdToDepositor[depositIds[i]].user == address(0)) { revert DepositorNull(); } if (depositIdToDepositor[depositIds[i]].priceId != 0) { revert PriceIdAlreadySet(); } depositIdToDepositor[depositIds[i]].priceId = priceIds[i]; emit PriceIdSetForDeposit(depositIds[i], priceIds[i]); } } /** * @notice Admin function to associate redemptionId with a given priceId * * @param redemptionIds an Array of redemptionIds to associate * @param priceIds an Array of priceIds to associate */ function setPriceIdForRedemptions( bytes32[] calldata redemptionIds, uint256[] calldata priceIds ) external virtual onlyRole(PRICE_ID_SETTER_ROLE) { uint256 redemptionsSize = redemptionIds.length; if (redemptionsSize != priceIds.length) { revert ArraySizeMismatch(); } for (uint256 i = 0; i < redemptionsSize; ++i) { if (redemptionIdToRedeemer[redemptionIds[i]].priceId != 0) { revert PriceIdAlreadySet(); } redemptionIdToRedeemer[redemptionIds[i]].priceId = priceIds[i]; emit PriceIdSetForRedemption(redemptionIds[i], priceIds[i]); } } /*////////////////////////////////////////////////////////////// Admin Setters //////////////////////////////////////////////////////////////*/ /** * @notice Admin function to overwrite entries in the depoitIdToDepositor * mapping * * @param depositIdToOverwrite The depositId of the entry we wish to * overwrite * @param user The user for the new entry * @param depositAmountAfterFee The deposit value for the new entry * @param priceId The priceId to be associated with the new * entry */ function overwriteDepositor( bytes32 depositIdToOverwrite, address user, uint256 depositAmountAfterFee, uint256 priceId ) external onlyRole(MANAGER_ADMIN) checkRestrictions(user) { Depositor memory oldDepositor = depositIdToDepositor[depositIdToOverwrite]; depositIdToDepositor[depositIdToOverwrite] = Depositor( user, depositAmountAfterFee, priceId ); emit DepositorOverwritten( depositIdToOverwrite, oldDepositor.user, user, oldDepositor.priceId, priceId, oldDepositor.amountDepositedMinusFees, depositAmountAfterFee ); } /** * @notice Admin function to overwrite entries in the redemptionIdToRedeemer * mapping * * @param redemptionIdToOverwrite The redemptionId of the entry we wish to * overwrite * @param user The user for the new entry * @param rwaTokenAmountBurned The burn amount for the new entry * @param priceId The priceID to be associated with the new * entry */ function overwriteRedeemer( bytes32 redemptionIdToOverwrite, address user, uint256 rwaTokenAmountBurned, uint256 priceId ) external onlyRole(MANAGER_ADMIN) checkRestrictions(user) { Redeemer memory oldRedeemer = redemptionIdToRedeemer[ redemptionIdToOverwrite ]; redemptionIdToRedeemer[redemptionIdToOverwrite] = Redeemer( user, rwaTokenAmountBurned, priceId ); emit RedeemerOverwritten( redemptionIdToOverwrite, oldRedeemer.user, user, oldRedeemer.priceId, priceId, oldRedeemer.amountRwaTokenBurned, rwaTokenAmountBurned ); } /** * @notice Admin function to set the minimum amount to redeem * * @param _minimumRedemptionAmount The minimum amount required to submit a * redemption request */ function setMinimumRedemptionAmount( uint256 _minimumRedemptionAmount ) external onlyRole(MANAGER_ADMIN) { if (_minimumRedemptionAmount < BPS_DENOMINATOR) { revert AmountTooSmall(); } uint256 oldRedeemMinimum = minimumRedemptionAmount; minimumRedemptionAmount = _minimumRedemptionAmount; emit MinimumRedemptionAmountSet(oldRedeemMinimum, _minimumRedemptionAmount); } /** * @notice Admin function to set the minimum amount required for a deposit * * @param minDepositAmount The minimum amount required to submit a deposit * request */ function setMinimumDepositAmount( uint256 minDepositAmount ) external onlyRole(MANAGER_ADMIN) { if (minDepositAmount < BPS_DENOMINATOR) { revert AmountTooSmall(); } uint256 oldMinimumDepositAmount = minimumDepositAmount; minimumDepositAmount = minDepositAmount; emit MinimumDepositAmountSet(oldMinimumDepositAmount, minDepositAmount); } /** * @notice Admin function to set the mint fee * * @param _mintFee The new mint fee specified in basis points * * @dev The maximum fee that can be set is 10_000 bps, or 100% */ function setMintFee(uint256 _mintFee) external onlyRole(MANAGER_ADMIN) { if (_mintFee > BPS_DENOMINATOR) { revert FeeTooLarge(); } uint256 oldMintFee = mintFee; mintFee = _mintFee; emit MintFeeSet(oldMintFee, _mintFee); } /** * @notice Admin function to set the redeem fee * * @param _redemptionFee The new redeem fee specified in basis points * * @dev The maximum fee that can be set is 10_000 bps, or 100% */ function setRedemptionFee( uint256 _redemptionFee ) external onlyRole(MANAGER_ADMIN) { if (_redemptionFee > BPS_DENOMINATOR) { revert FeeTooLarge(); } uint256 oldRedeemFee = redemptionFee; redemptionFee = _redemptionFee; emit RedemptionFeeSet(oldRedeemFee, _redemptionFee); } /** * @notice Admin function to set the address of the Pricer contract * * @param newPricer The address of the new pricer contract */ function setPricer(address newPricer) external onlyRole(MANAGER_ADMIN) { address oldPricer = address(pricer); pricer = IPricerReader(newPricer); emit NewPricerSet(oldPricer, newPricer); } /** * @notice Admin function to set the address of `feeRecipient` * * @param newFeeRecipient The address of the new `feeRecipient` */ function setFeeRecipient( address newFeeRecipient ) external onlyRole(MANAGER_ADMIN) { address oldFeeRecipient = feeRecipient; feeRecipient = newFeeRecipient; emit FeeRecipientSet(oldFeeRecipient, feeRecipient); } /** * @notice Admin function to set the address of `assetSender` * * @param newAssetSender The address of the new `assetSender` */ function setAssetSender( address newAssetSender ) external onlyRole(MANAGER_ADMIN) { address oldAssetSender = assetSender; assetSender = newAssetSender; emit AssetSenderSet(oldAssetSender, newAssetSender); } /*////////////////////////////////////////////////////////////// Pause Utils //////////////////////////////////////////////////////////////*/ /** * @notice Modifier to check if a feature is paused * * @param feature The feature to check if paused */ modifier ifNotPaused(bool feature) { if (feature) { revert FeaturePaused(); } _; } /** * @notice Function to pause subscription to RWAHub */ function pauseSubscription() external onlyRole(PAUSER_ADMIN) { subscriptionPaused = true; emit SubscriptionPaused(msg.sender); } /** * @notice Function to pause redemptions to RWAHub */ function pauseRedemption() external onlyRole(PAUSER_ADMIN) { redemptionPaused = true; emit RedemptionPaused(msg.sender); } /** * @notice Function to unpause subscriptions to RWAHub */ function unpauseSubscription() external onlyRole(MANAGER_ADMIN) { subscriptionPaused = false; emit SubscriptionUnpaused(msg.sender); } /** * @notice Function to unpause redemptions to RWAHub */ function unpauseRedemption() external onlyRole(MANAGER_ADMIN) { redemptionPaused = false; emit RedemptionUnpaused(msg.sender); } /*////////////////////////////////////////////////////////////// Check Restriction Utils //////////////////////////////////////////////////////////////*/ /** * @notice Modifier to check restrictions status of an account * * @param account The account to check */ modifier checkRestrictions(address account) { _checkRestrictions(account); _; } /** * @notice internal function to check restriction status * of an address * * @param account The account to check restriction status for * * @dev This function is virtual to be overridden by child contract * to check restrictions on a more granular level */ function _checkRestrictions(address account) internal view virtual; /*////////////////////////////////////////////////////////////// Math Utils //////////////////////////////////////////////////////////////*/ /** * @notice Given amount of `collateral`, returns how much in fees * are owed * * * @param collateralAmount Amount `collateral` to calculate fees * (in decimals of `collateral`) */ function _getMintFees( uint256 collateralAmount ) internal view returns (uint256) { return (collateralAmount * mintFee) / BPS_DENOMINATOR; } /** * @notice Given amount of `collateral`, returns how much in fees * are owed * * @param collateralAmount Amount of `collateral` to calculate fees * (in decimals of `collateral`) */ function _getRedemptionFees( uint256 collateralAmount ) internal view returns (uint256) { return (collateralAmount * redemptionFee) / BPS_DENOMINATOR; } /** * @notice Given a deposit amount and priceId, returns the amount * of `rwa` due * * @param depositAmt The amount deposited in units of `collateral` * @param price The price associated with this deposit */ function _getMintAmountForPrice( uint256 depositAmt, uint256 price ) internal view returns (uint256 rwaAmountOut) { uint256 amountE36 = _scaleUp(depositAmt) * 1e18; // Will revert with div by 0 if price not defined for a priceId rwaAmountOut = amountE36 / price; } /** * @notice Given a redemption amount and a priceId, returns the amount * of `collateral` due * * @param rwaTokenAmountBurned The amount of `rwa` burned for a redemption * @param price The price associated with this redemption */ function _getRedemptionAmountForRwa( uint256 rwaTokenAmountBurned, uint256 price ) internal view returns (uint256 collateralOwed) { uint256 amountE36 = rwaTokenAmountBurned * price; collateralOwed = _scaleDown(amountE36 / 1e18); } /** * @notice Scale provided amount up by `decimalsMultiplier` * * @dev This helper is used for converting the collateral's decimals * representation to the RWA amount decimals representation. */ function _scaleUp(uint256 amount) internal view returns (uint256) { return amount * decimalsMultiplier; } /** * @notice Scale provided amount down by `decimalsMultiplier` * * @dev This helper is used for converting `rwa`'s decimal * representation to the `collateral`'s decimal representation */ function _scaleDown(uint256 amount) internal view returns (uint256) { return amount / decimalsMultiplier; } }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; interface IRWAHub { // Struct to contain the deposit information for a given depositId struct Depositor { address user; uint256 amountDepositedMinusFees; uint256 priceId; } // Struc to contain withdrawal infromation for a given redemptionId struct Redeemer { address user; uint256 amountRwaTokenBurned; uint256 priceId; } function requestSubscription(uint256 amount) external; function claimMint(bytes32[] calldata depositIds) external; function requestRedemption(uint256 amount) external; function claimRedemption(bytes32[] calldata redemptionIds) external; function addProof( bytes32 txHash, address user, uint256 depositAmountAfterFee, uint256 feeAmount, uint256 timestamp ) external; function setPriceIdForDeposits( bytes32[] calldata depositIds, uint256[] calldata priceIds ) external; function setPriceIdForRedemptions( bytes32[] calldata redemptionIds, uint256[] calldata priceIds ) external; function setPricer(address newPricer) external; function overwriteDepositor( bytes32 depositIdToOverride, address user, uint256 depositAmountAfterFee, uint256 priceId ) external; function overwriteRedeemer( bytes32 redemptionIdToOverride, address user, uint256 rwaTokenAmountBurned, uint256 priceId ) external; /** * @notice Event emitted when fee recipient is set * * @param oldFeeRecipient Old fee recipient * @param newFeeRecipient New fee recipient */ event FeeRecipientSet(address oldFeeRecipient, address newFeeRecipient); /** * @notice Event emitted when the assetSender is changed * * @param oldAssetSender The address of the old assetSender * @param newAssetSender The address of the new assetSender */ event AssetSenderSet(address oldAssetSender, address newAssetSender); /** * @notice Event emitted when minimum deposit amount is set * * @param oldMinimum Old minimum * @param newMinimum New minimum * * @dev See inheriting contract for decimals representation */ event MinimumDepositAmountSet(uint256 oldMinimum, uint256 newMinimum); /** * @notice Event emitted when a new redeem minimum is set. * All units are in 1e18 * * @param oldRedemptionMin The old redeem minimum value * @param newRedemptionMin The new redeem minimum value */ event MinimumRedemptionAmountSet( uint256 oldRedemptionMin, uint256 newRedemptionMin ); /** * @notice Event emitted when mint fee is set * * @param oldFee Old fee * @param newFee New fee * * @dev See inheriting contract for decimals representation */ event MintFeeSet(uint256 oldFee, uint256 newFee); /** * @notice Event emitted when redeem fee is set * * @param oldFee Old fee * @param newFee New fee * * @dev see inheriting contract for decimal representation */ event RedemptionFeeSet(uint256 oldFee, uint256 newFee); /** * @notice Event emitted when redemption request is submitted * * @param user The user submitting the redemption request * @param redemptionId The id corresponding to a given redemption * @param rwaAmountIn The amount of cash being burned */ event RedemptionRequested( address indexed user, bytes32 indexed redemptionId, uint256 rwaAmountIn ); /** * @notice Event emitted when a mint request is submitted * * @param user The user requesting to mint * @param depositId The depositId of the request * @param collateralAmountDeposited The total amount deposited * @param depositAmountAfterFee The value deposited - fee * @param feeAmount The fee amount taken * (units of collateral) */ event MintRequested( address indexed user, bytes32 indexed depositId, uint256 collateralAmountDeposited, uint256 depositAmountAfterFee, uint256 feeAmount ); /** * @notice Event emitted when a redemption request is completed * * @param user The address of the user getting the funds * @param redemptionId The id corresponding to a given redemption * requested * @param rwaAmountRequested Amount of RWA originally requested by the user * @param collateralAmountReturned Amount of collateral received by the user * @param price The price at which the redemption was * serviced at */ event RedemptionCompleted( address indexed user, bytes32 indexed redemptionId, uint256 rwaAmountRequested, uint256 collateralAmountReturned, uint256 price ); /** * @notice Event emitted when a Mint request is completed * * @param user The address of the user getting the funds * @param depositId The depositId of the mint request * @param rwaAmountOut The amount of RWA token minted to the * user * @param collateralAmountDeposited The amount of collateral deposited * @param price The price set for the given * deposit id * @param priceId The priceId used to determine price */ event MintCompleted( address indexed user, bytes32 indexed depositId, uint256 rwaAmountOut, uint256 collateralAmountDeposited, uint256 price, uint256 priceId ); /** * @notice Event emitted when a deposit has its corresponding priceId set * * @param depositIdSet The Deposit Id for which the price Id is being set * @param priceIdSet The price Id being associate with a deposit Id */ event PriceIdSetForDeposit( bytes32 indexed depositIdSet, uint256 indexed priceIdSet ); /** * @notice Event Emitted when a redemption has its corresponding priceId set * * @param redemptionIdSet The Redemption Id for which the price Id is being * set * @param priceIdSet The Price Id being associated with a redemption Id */ event PriceIdSetForRedemption( bytes32 indexed redemptionIdSet, uint256 indexed priceIdSet ); /** * @notice Event emitted when a new Pricer contract is set * * @param oldPricer The address of the old pricer contract * @param newPricer The address of the new pricer contract */ event NewPricerSet(address oldPricer, address newPricer); /** * @notice Event emitted when deposit proof has been added * * @param txHash Tx hash of the deposit * @param user Address of the user who made the deposit * @param depositAmountAfterFee Amount of the deposit after fees * @param feeAmount Amount of fees taken * @param timestamp Timestamp of the deposit */ event DepositProofAdded( bytes32 indexed txHash, address indexed user, uint256 depositAmountAfterFee, uint256 feeAmount, uint256 timestamp ); /** * @notice Event emitted when subscriptions are paused * * @param caller Address which initiated the pause */ event SubscriptionPaused(address caller); /** * @notice Event emitted when redemptions are paused * * @param caller Address which initiated the pause */ event RedemptionPaused(address caller); /** * @notice Event emitted when subscriptions are unpaused * * @param caller Address which initiated the unpause */ event SubscriptionUnpaused(address caller); /** * @notice Event emitted when redemptions are unpaused * * @param caller Address which initiated the unpause */ event RedemptionUnpaused(address caller); event DepositorOverwritten( bytes32 indexed depositId, address oldDepositor, address newDepositor, uint256 oldPriceId, uint256 newPriceId, uint256 oldDepositAmount, uint256 newDepositAmount ); event RedeemerOverwritten( bytes32 indexed redemptionId, address oldRedeemer, address newRedeemer, uint256 oldPriceId, uint256 newPriceId, uint256 oldRWATokenAmountBurned, uint256 newRWATokenAmountBurned ); /// ERRORS /// error PriceIdNotSet(); error ArraySizeMismatch(); error DepositTooSmall(); error RedemptionTooSmall(); error TxnAlreadyValidated(); error CollateralCannotBeZero(); error RWACannotBeZero(); error AssetSenderCannotBeZero(); error FeeRecipientCannotBeZero(); error FeeTooLarge(); error AmountTooSmall(); error DepositorNull(); error RedeemerNull(); error DepositProofAlreadyExists(); error FeaturePaused(); error PriceIdAlreadySet(); }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; interface IPricerReader { /** * @notice Gets the latest price of the asset * * @return uint256 The latest price of the asset */ function getLatestPrice() external view returns (uint256); /** * @notice Gets the price of the asset at a specific priceId * * @param priceId The priceId at which to get the price * * @return uint256 The price of the asset with the given priceId */ function getPrice(uint256 priceId) external view returns (uint256); }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; // This interface is not inherited directly by RWA, instead, it is a // subset of functions provided by all RWA tokens that the RWA Hub // Client uses. import "contracts/external/openzeppelin/contracts/token/IERC20.sol"; interface IRWALike is IERC20 { function mint(address to, uint256 amount) external; function burn(uint256 amount) external; function burnFrom(address from, uint256 amount) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) pragma solidity ^0.8.0; import "contracts/external/openzeppelin/contracts/access/IAccessControlEnumerable.sol"; import "contracts/external/openzeppelin/contracts/access/AccessControl.sol"; import "contracts/external/openzeppelin/contracts/utils/EnumerableSet.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { using EnumerableSet for EnumerableSet.AddressSet; mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { return _roleMembers[role].at(index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { return _roleMembers[role].length(); } /** * @dev Overload {_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override { super._grantRole(role, account); _roleMembers[role].add(account); } /** * @dev Overload {_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override { super._revokeRole(role, account); _roleMembers[role].remove(account); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "contracts/external/openzeppelin/contracts/token/IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "contracts/external/openzeppelin/contracts/token/IERC20.sol"; import "contracts/external/openzeppelin/contracts/utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transfer.selector, to, value) ); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value) ); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn( token, abi.encodeWithSelector(token.approve.selector, spender, value) ); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn( token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance) ); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require( oldAllowance >= value, "SafeERC20: decreased allowance below zero" ); uint256 newAllowance = oldAllowance - value; _callOptionalReturn( token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance) ); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require( abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed" ); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) pragma solidity ^0.8.0; import "contracts/external/openzeppelin/contracts/access/IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "contracts/external/openzeppelin/contracts/access/IAccessControl.sol"; import "contracts/external/openzeppelin/contracts/utils/Context.sol"; import "contracts/external/openzeppelin/contracts/utils/Strings.sol"; import "contracts/external/openzeppelin/contracts/utils/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require( account == _msgSender(), "AccessControl: can only renounce roles for self" ); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged( bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole ); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted( bytes32 indexed role, address indexed account, address indexed sender ); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked( bytes32 indexed role, address indexed account, address indexed sender ); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "contracts/external/openzeppelin/contracts/utils/IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require( success, "Address: unable to send value, recipient may have reverted" ); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue( target, data, value, "Address: low-level call with value failed" ); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require( address(this).balance >= value, "Address: insufficient balance for call" ); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall( target, data, "Address: low-level delegate call failed" ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; import "contracts/external/chainalysis/ISanctionsList.sol"; /** * @title ISanctionsListClient * @author Ondo Finance * @notice The client interface for sanctions contract. */ interface ISanctionsListClient { /// @notice Returns reference to the sanctions list that this client queries function sanctionsList() external view returns (ISanctionsList); /// @notice Sets the sanctions list reference function setSanctionsList(address sanctionsList) external; /// @notice Error for when caller attempts to set the `sanctionsList` /// reference to the zero address error SanctionsListZeroAddress(); /// @notice Error for when caller attempts to perform an action on a /// sanctioned account error SanctionedAccount(); /** * @dev Event for when the sanctions list reference is set * * @param oldSanctionsList The old list * @param newSanctionsList The new list */ event SanctionsListSet(address oldSanctionsList, address newSanctionsList); }
/// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.16; interface ISanctionsList { function isSanctioned(address addr) external view returns (bool); }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; interface IBlocklist { function addToBlocklist(address[] calldata accounts) external; function removeFromBlocklist(address[] calldata accounts) external; function isBlocked(address account) external view returns (bool); /** * @notice Event emitted when addresses are added to the blocklist * * @param accounts The addresses that were added to the blocklist */ event BlockedAddressesAdded(address[] accounts); /** * @notice Event emitted when addresses are removed from the blocklist * * @param accounts The addresses that were removed from the blocklist */ event BlockedAddressesRemoved(address[] accounts); }
/**SPDX-License-Identifier: BUSL-1.1 ▄▄█████████▄ ╓██▀└ ,╓▄▄▄, '▀██▄ ██▀ ▄██▀▀╙╙▀▀██▄ └██µ ,, ,, , ,,, ,,, ██ ,██¬ ▄████▄ ▀█▄ ╙█▄ ▄███▀▀███▄ ███▄ ██ ███▀▀▀███▄ ▄███▀▀███, ██ ██ ╒█▀' ╙█▌ ╙█▌ ██ ▐██ ███ █████, ██ ██▌ └██▌ ██▌ └██▌ ██ ▐█▌ ██ ╟█ █▌ ╟█ ██▌ ▐██ ██ └███ ██ ██▌ ╟██ j██ ╟██ ╟█ ██ ╙██ ▄█▀ ▐█▌ ██ ╙██ ██▌ ██ ╙████ ██▌ ▄██▀ ██▌ ,██▀ ██ "██, ╙▀▀███████████⌐ ╙████████▀ ██ ╙██ ███████▀▀ ╙███████▀` ██▄ ╙▀██▄▄▄▄▄,,, ¬─ '─¬ ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀ ╙▀▀██████R⌐ */ pragma solidity 0.8.16; import "contracts/interfaces/IBlocklist.sol"; /** * @title IBlocklistClient * @author Ondo Finance * @notice The client interface for the Blocklist contract. */ interface IBlocklistClient { /// @notice Returns reference to the blocklist that this client queries function blocklist() external view returns (IBlocklist); /// @notice Sets the blocklist reference function setBlocklist(address registry) external; /// @notice Error for when caller attempts to set the blocklist reference /// to the zero address error BlocklistZeroAddress(); /// @notice Error for when caller attempts to perform action on a blocked /// account error BlockedAccount(); /** * @dev Event for when the blocklist reference is set * * @param oldBlocklist The old blocklist * @param newBlocklist The new blocklist */ event BlocklistSet(address oldBlocklist, address newBlocklist); }
{ "optimizer": { "enabled": true, "runs": 100 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"address","name":"_rwa","type":"address"},{"internalType":"address","name":"managerAdmin","type":"address"},{"internalType":"address","name":"pauser","type":"address"},{"internalType":"address","name":"_assetSender","type":"address"},{"internalType":"address","name":"_feeRecipient","type":"address"},{"internalType":"uint256","name":"_minimumDepositAmount","type":"uint256"},{"internalType":"uint256","name":"_minimumRedemptionAmount","type":"uint256"},{"internalType":"address","name":"blocklist","type":"address"},{"internalType":"address","name":"sanctionsList","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AmountTooSmall","type":"error"},{"inputs":[],"name":"ArraySizeMismatch","type":"error"},{"inputs":[],"name":"AssetSenderCannotBeZero","type":"error"},{"inputs":[],"name":"BlockedAccount","type":"error"},{"inputs":[],"name":"BlocklistZeroAddress","type":"error"},{"inputs":[],"name":"ClaimableTimestampInPast","type":"error"},{"inputs":[],"name":"ClaimableTimestampNotSet","type":"error"},{"inputs":[],"name":"CollateralCannotBeZero","type":"error"},{"inputs":[],"name":"DepositProofAlreadyExists","type":"error"},{"inputs":[],"name":"DepositTooSmall","type":"error"},{"inputs":[],"name":"DepositorNull","type":"error"},{"inputs":[],"name":"FeaturePaused","type":"error"},{"inputs":[],"name":"FeeRecipientCannotBeZero","type":"error"},{"inputs":[],"name":"FeeTooLarge","type":"error"},{"inputs":[],"name":"MintNotYetClaimable","type":"error"},{"inputs":[],"name":"PriceIdAlreadySet","type":"error"},{"inputs":[],"name":"PriceIdNotSet","type":"error"},{"inputs":[],"name":"RWACannotBeZero","type":"error"},{"inputs":[],"name":"RedeemerNull","type":"error"},{"inputs":[],"name":"RedemptionTooSmall","type":"error"},{"inputs":[],"name":"SanctionedAccount","type":"error"},{"inputs":[],"name":"SanctionsListZeroAddress","type":"error"},{"inputs":[],"name":"TxnAlreadyValidated","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAssetSender","type":"address"},{"indexed":false,"internalType":"address","name":"newAssetSender","type":"address"}],"name":"AssetSenderSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldBlocklist","type":"address"},{"indexed":false,"internalType":"address","name":"newBlocklist","type":"address"}],"name":"BlocklistSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"claimTimestamp","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"depositId","type":"bytes32"}],"name":"ClaimableTimestampSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"depositAmountAfterFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"DepositProofAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"depositId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"oldDepositor","type":"address"},{"indexed":false,"internalType":"address","name":"newDepositor","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldPriceId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPriceId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldDepositAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDepositAmount","type":"uint256"}],"name":"DepositorOverwritten","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldFeeRecipient","type":"address"},{"indexed":false,"internalType":"address","name":"newFeeRecipient","type":"address"}],"name":"FeeRecipientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMinimum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinimum","type":"uint256"}],"name":"MinimumDepositAmountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRedemptionMin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRedemptionMin","type":"uint256"}],"name":"MinimumRedemptionAmountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bytes32","name":"depositId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"rwaAmountOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmountDeposited","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceId","type":"uint256"}],"name":"MintCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"MintFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bytes32","name":"depositId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"collateralAmountDeposited","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositAmountAfterFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"MintRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPricer","type":"address"},{"indexed":false,"internalType":"address","name":"newPricer","type":"address"}],"name":"NewPricerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMinimum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinimum","type":"uint256"}],"name":"OffChainRedemptionMinimumSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"OffChainRedemptionPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"OffChainRedemptionUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"depositIdSet","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"priceIdSet","type":"uint256"}],"name":"PriceIdSetForDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"redemptionIdSet","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"priceIdSet","type":"uint256"}],"name":"PriceIdSetForRedemption","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"redemptionId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"oldRedeemer","type":"address"},{"indexed":false,"internalType":"address","name":"newRedeemer","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldPriceId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPriceId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldRWATokenAmountBurned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRWATokenAmountBurned","type":"uint256"}],"name":"RedeemerOverwritten","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bytes32","name":"redemptionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"rwaAmountRequested","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmountReturned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"RedemptionCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"RedemptionFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"RedemptionPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bytes32","name":"redemptionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"rwaAmountIn","type":"uint256"}],"name":"RedemptionRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"bytes32","name":"redemptionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"rwaTokenAmountIn","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"offChainDestination","type":"bytes32"}],"name":"RedemptionRequestedServicedOffChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"RedemptionUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldSanctionsList","type":"address"},{"indexed":false,"internalType":"address","name":"newSanctionsList","type":"address"}],"name":"SanctionsListSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"SubscriptionPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"SubscriptionUnpaused","type":"event"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGER_ADMIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAUSER_ADMIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_ID_SETTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMESTAMP_SETTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"txHash","type":"bytes32"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"depositAmountAfterFee","type":"uint256"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"addProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"assetRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocklist","outputs":[{"internalType":"contract IBlocklist","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"depositIds","type":"bytes32[]"}],"name":"claimMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"redemptionIds","type":"bytes32[]"}],"name":"claimRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalsMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"depositIdToClaimableTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"depositIdToDepositor","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amountDepositedMinusFees","type":"uint256"},{"internalType":"uint256","name":"priceId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumDepositAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumOffChainRedemptionAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumRedemptionAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"offChainRedemptionPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"depositIdToOverwrite","type":"bytes32"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"depositAmountAfterFee","type":"uint256"},{"internalType":"uint256","name":"priceId","type":"uint256"}],"name":"overwriteDepositor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"redemptionIdToOverwrite","type":"bytes32"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"rwaTokenAmountBurned","type":"uint256"},{"internalType":"uint256","name":"priceId","type":"uint256"}],"name":"overwriteRedeemer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseOffChainRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pricer","outputs":[{"internalType":"contract IPricerReader","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"redemptionIdToRedeemer","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amountRwaTokenBurned","type":"uint256"},{"internalType":"uint256","name":"priceId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionRequestCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"requestRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountRWATokenToRedeem","type":"uint256"},{"internalType":"bytes32","name":"offChainDestination","type":"bytes32"}],"name":"requestRedemptionServicedOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"requestSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rwa","outputs":[{"internalType":"contract IRWALike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sanctionsList","outputs":[{"internalType":"contract ISanctionsList","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAssetSender","type":"address"}],"name":"setAssetSender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"blocklist","type":"address"}],"name":"setBlocklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"claimTimestamp","type":"uint256"},{"internalType":"bytes32[]","name":"depositIds","type":"bytes32[]"}],"name":"setClaimableTimestamp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeRecipient","type":"address"}],"name":"setFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minDepositAmount","type":"uint256"}],"name":"setMinimumDepositAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimumRedemptionAmount","type":"uint256"}],"name":"setMinimumRedemptionAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintFee","type":"uint256"}],"name":"setMintFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimumOffChainRedemptionAmount","type":"uint256"}],"name":"setOffChainRedemptionMinimum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"depositIds","type":"bytes32[]"},{"internalType":"uint256[]","name":"priceIds","type":"uint256[]"}],"name":"setPriceIdForDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"redemptionIds","type":"bytes32[]"},{"internalType":"uint256[]","name":"priceIds","type":"uint256[]"}],"name":"setPriceIdForRedemptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPricer","type":"address"}],"name":"setPricer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_redemptionFee","type":"uint256"}],"name":"setRedemptionFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sanctionsList","type":"address"}],"name":"setSanctionsList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subscriptionPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"subscriptionRequestCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpauseOffChainRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e06040526000600a556000600b556001600c556001600d553480156200002557600080fd5b5060405162003b7138038062003b718339810160408190526200004891620005ff565b600160005580828b8b8b8b8b8b8b8b87878787878787876001600160a01b038816620000875760405163a1aeceb760e01b815260040160405180910390fd5b6001600160a01b038716620000af5760405163071aeb1d60e01b815260040160405180910390fd5b6001600160a01b038416620000d757604051633b2b1d5560e01b815260040160405180910390fd5b6001600160a01b038316620000ff57604051634fdcfc5560e11b815260040160405180910390fd5b6200010c6000876200034a565b6200012760008051602062003b51833981519152876200034a565b6200014260008051602062003b31833981519152866200034a565b6200016c60008051602062003b3183398151915260008051602062003b518339815191526200038d565b620001a77f830a9081649e91840eb0274e99b47626a896cfa0f4dd591cb31cd5060e566c0d60008051602062003b518339815191526200038d565b620001e27fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc460008051602062003b518339815191526200038d565b6001600160a01b0388811660a0819052888216608052600580546001600160a01b03199081168785161790915560048054909116928716929092178255600884905560098390556040805163313ce56760e01b81529051919263313ce5679282820192602092908290030181865afa15801562000263573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002899190620006bc565b876001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002c8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002ee9190620006bc565b620002fa9190620006fe565b6200030790600a62000817565b60c052505050600f95909555506200032d9a508b995050620003da975050505050505050565b50620003398162000464565b505050505050505050505062000828565b620003618282620004e760201b62001fd11760201c565b6000828152600260209081526040909120620003889183906200203c62000570821b17901c565b505050565b6000828152600160208190526040808320909101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6001600160a01b0381166200040257604051637e33865360e01b815260040160405180910390fd5b601080546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f7e053cdc9069fe4f629b6b3fa2a01bb53a9a8305ec11830b259d95e9e75b730491015b60405180910390a15050565b6001600160a01b0381166200048c576040516310ce5abd60e21b815260040160405180910390fd5b601180546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527fa19fd4029e820c57308467576d8d0296f07717cfcb98941cf8988b25dcd700e3910162000458565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff166200056c5760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45b5050565b600062000587836001600160a01b03841662000590565b90505b92915050565b6000818152600183016020526040812054620005d9575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200058a565b5060006200058a565b80516001600160a01b0381168114620005fa57600080fd5b919050565b6000806000806000806000806000806101408b8d0312156200062057600080fd5b6200062b8b620005e2565b99506200063b60208c01620005e2565b98506200064b60408c01620005e2565b97506200065b60608c01620005e2565b96506200066b60808c01620005e2565b95506200067b60a08c01620005e2565b945060c08b0151935060e08b015192506200069a6101008c01620005e2565b9150620006ab6101208c01620005e2565b90509295989b9194979a5092959850565b600060208284031215620006cf57600080fd5b815160ff81168114620006e157600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b60ff82811682821603908111156200058a576200058a620006e8565b600181815b808511156200075b5781600019048211156200073f576200073f620006e8565b808516156200074d57918102915b93841c93908002906200071f565b509250929050565b60008262000774575060016200058a565b8162000783575060006200058a565b81600181146200079c5760028114620007a757620007c7565b60019150506200058a565b60ff841115620007bb57620007bb620006e8565b50506001821b6200058a565b5060208310610133831016604e8410600b8410161715620007ec575081810a6200058a565b620007f883836200071a565b80600019048211156200080f576200080f620006e8565b029392505050565b60006200058760ff84168362000763565b60805160a05160c05161329a62000897600039600081816106f1015281816126620152612c5701526000818161079e01528181610b3301528181610bfb0152818161199d01526119d501526000818161067601528181611dd401528181611f2001526128f5015261329a6000f3fe608060405234801561001057600080fd5b50600436106103505760003560e01c80638d044c06116101bf578063d547741f116100fa578063e4107c971161009d578063e4107c97146107f8578063e74b981b1461080b578063ec571c6a1461081e578063eddd0d9c14610831578063ee75d7d414610844578063eeb3c91014610857578063f4a203071461086a578063f80a36d61461089157600080fd5b8063d547741f14610760578063d592d81514610773578063d64e539614610786578063d8dfeb4514610799578063dd45eef6146107c0578063de6afa82146107d3578063e0f486ef146107e6578063e1a45218146107ef57600080fd5b8063aa85c1df11610162578063aa85c1df146106b3578063aab483d6146106c6578063aef18ae7146106d9578063bb13245f146106ec578063bcc7028314610713578063ca15c87314610728578063cd4d0bcf1461073b578063d0c835ce1461074d57600080fd5b80638d044c06146106145780639010d07c1461061c57806391d148541461062f578063926d7d7f1461064257806392bccb801461066957806395e4b25114610671578063a217fddf14610698578063a6138ed9146106a057600080fd5b80633bfa67fe1161028f578063525decd611610232578063525decd6146105585780635d591d681461056b57806373a95ddd146105a45780637dbc1df0146105b1578063837018fa146105c457806385c4e79e146105cc57806387e2d06e146105e15780638a07df1e146105f457600080fd5b80633bfa67fe146104cb5780634565e9ff146104f3578063458f581514610506578063469048401461050f57806349cbbf2a1461052257806349dc5e8d1461052a5780634dfe7af21461053d5780634ef1ccd11461054557600080fd5b8063248a9ca3116102f7578063248a9ca3146103e1578063258492cd1461040557806329390370146104185780632b5eceff1461042b5780632f2ff15d1461043e578063354181f31461045157806336568abe1461045a57806338fed7081461046d57600080fd5b806301ffc9a714610355578063078a6be81461037d57806307bda1bb146103a0578063080c279a146103a957806312589fb5146103b257806313966db5146103bb5780632056aa12146103c4578063244f5acf146103ce575b600080fd5b610368610363366004612cb5565b6108a4565b60405190151581526020015b60405180910390f35b61039260008051602061324583398151915281565b604051908152602001610374565b610392600c5481565b61039260085481565b610392600f5481565b610392600a5481565b6103cc6108cf565b005b6103cc6103dc366004612d2b565b610932565b6103926103ef366004612d6d565b6000908152600160208190526040909120015490565b6103cc610413366004612da2565b610c34565b6103cc610426366004612ddd565b610d8e565b6103cc610439366004612df8565b610e07565b6103cc61044c366004612e3e565b610f16565b610392600d5481565b6103cc610468366004612e3e565b610f42565b6104a661047b366004612d6d565b6007602052600090815260409020805460018201546002909201546001600160a01b03909116919083565b604080516001600160a01b039094168452602084019290925290820152606001610374565b6104e673bda73a0f13958ee444e0782e1768ab4b76edae2881565b6040516103749190612e6a565b6103cc610501366004612d2b565b610fc0565b610392600b5481565b6005546104e6906001600160a01b031681565b6103cc61104e565b6103cc610538366004612ddd565b6110a8565b6103cc6110ca565b6103cc610553366004612d6d565b61111f565b6103cc610566366004612ddd565b611199565b6104a6610579366004612d6d565b6006602052600090815260409020805460018201546002909201546001600160a01b03909116919083565b600e546103689060ff1681565b6103cc6105bf366004612d6d565b611205565b6103cc61127f565b61039260008051602061320583398151915281565b6103cc6105ef366004612e7e565b6112d3565b610392610602366004612d6d565b60446020526000908152604090205481565b6103cc611481565b6104e661062a366004612eea565b6114d4565b61036861063d366004612e3e565b6114f3565b6103927fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6103cc61151e565b6104e67f000000000000000000000000000000000000000000000000000000000000000081565b610392600081565b6003546104e6906001600160a01b031681565b6103cc6106c1366004612e7e565b611574565b6103cc6106d4366004612d6d565b6116c0565b6103cc6106e7366004612ddd565b61173a565b6103927f000000000000000000000000000000000000000000000000000000000000000081565b61039260008051602061322583398151915281565b610392610736366004612d6d565b61175c565b600e5461036890610100900460ff1681565b6103cc61075b366004612f0c565b611773565b6103cc61076e366004612e3e565b611859565b6103cc610781366004612d6d565b611880565b6010546104e6906001600160a01b031681565b6104e67f000000000000000000000000000000000000000000000000000000000000000081565b600e546103689062010000900460ff1681565b6103cc6107e1366004612da2565b611a63565b61039260095481565b61039261271081565b6103cc610806366004612d6d565b611bac565b6103cc610819366004612ddd565b611c03565b6011546104e6906001600160a01b031681565b6103cc61083f366004612d6d565b611c6e565b6004546104e6906001600160a01b031681565b6103cc610865366004612d6d565b611ce8565b6103927fced4eb9faeb19ab0e2e05a20ade58d82157e1035a3fbff4bc38dd5e609f22b9381565b6103cc61089f366004612eea565b611e7c565b60006001600160e01b03198216635a05180f60e01b14806108c957506108c982612051565b92915050565b6000805160206132058339815191526108e88133612086565b600e805461ff0019166101001790556040517fcd71257f2998474633e94cfffa045014068f6218ffdca256b6f4aa9d5f15fb8990610927903390612e6a565b60405180910390a150565b60026000540361095d5760405162461bcd60e51b815260040161095490612f58565b60405180910390fd5b6002600055600e5460ff1680156109875760405163aadfaddd60e01b815260040160405180910390fd5b600082815b81811015610be0576000600760008888858181106109ac576109ac612f8f565b60209081029290920135835250818101929092526040908101600020815160608101835281546001600160a01b0316808252600183015494820194909452600290910154918101919091529150610a02906120ea565b8060400151600003610a2757604051638718c77160e01b815260040160405180910390fd5b6003546040828101519051630e75722360e41b815260048101919091526000916001600160a01b03169063e757223090602401602060405180830381865afa158015610a77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9b9190612fa5565b90506000610aad83602001518361213b565b90506000610aba8261216c565b90506000610ac88284612fd4565b9050610ad48289612fe7565b9750600760008c8c89818110610aec57610aec612f8f565b60209081029290920135835250810191909152604001600090812080546001600160a01b031916815560018101829055600201556004548551610b5e916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169291169084612189565b8a8a87818110610b7057610b70612f8f565b87516020898101516040805191825281830188905281018a905292029390930135926001600160a01b031691507f35908d59be205275271010c5ea7062a88a2b5fbafe268bb9070550276f0edadd9060600160405180910390a3505050505080610bd990612ffa565b905061098c565b508115610c2857600454600554610c28916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811692918116911685612189565b50506001600055505050565b600080516020613245833981519152610c4d8133612086565b83610c57816120ea565b6000600760008881526020019081526020016000206040518060600160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201548152505090506040518060600160405280876001600160a01b03168152602001868152602001858152506007600089815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020155905050867f5a0c55c421ae3aac2379811eca16aaee32b6e64411322b624118d4219b9350a082600001518884604001518886602001518b604051610d7d96959493929190613013565b60405180910390a250505050505050565b600080516020613245833981519152610da78133612086565b600380546001600160a01b038481166001600160a01b03198316179092556040519116907f801352e72ef9b80b3992ccbedf07ab0e133e7da7aaccf0024abf23f4f32eb99a90610dfa9083908690613049565b60405180910390a1505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4610e328133612086565b84610e3c816120ea565b6000878152600660205260409020546001600160a01b031615610e7257604051631aeecebf60e21b815260040160405180910390fd5b60408051606080820183526001600160a01b0389811680845260208085018b815260008688018181528f82526006845290889020965187546001600160a01b031916951694909417865551600186015591516002909401939093558351898152908101889052928301869052909189917fc985471d1cb1bb75da0d54fa5ab10f7171e952cefcc0bf4fc7c2546c19d1811f910160405180910390a350505050505050565b60008281526001602081905260409091200154610f338133612086565b610f3d83836121e9565b505050565b6001600160a01b0381163314610fb25760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610954565b610fbc828261220b565b5050565b600260005403610fe25760405162461bcd60e51b815260040161095490612f58565b6002600055600e54610100900460ff1680156110115760405163aadfaddd60e01b815260040160405180910390fd5b8160005b81811015610c285761103e85858381811061103257611032612f8f565b9050602002013561222d565b61104781612ffa565b9050611015565b6000805160206132058339815191526110678133612086565b600e805462ff00001916620100001790556040517fdc41a92196ccc1ab8149c01bc68c2f506b10a7bb5cd2693c9516d176f5381ff490610927903390612e6a565b6000805160206132458339815191526110c18133612086565b610fbc826122a4565b6000805160206132458339815191526110e38133612086565b600e805462ff0000191690556040517f53a8c40fc17c78d38e2c06aa8d2c550c1acbf7b30d087dbda289ab3dd41c235c90610927903390612e6a565b6000805160206132458339815191526111388133612086565b61271082101561115b5760405163617ab12d60e11b815260040160405180910390fd5b600980549083905560408051828152602081018590527ffdaf6ed728cef208e62328a008209556f8281f3062b14dd08aaaa90fa15942119101610dfa565b6000805160206132458339815191526111b28133612086565b600480546001600160a01b038481166001600160a01b03198316179092556040519116907fb09f298b2812193d5ada18beaadd6cb8f12b3640926d99de46e2a65394df829d90610dfa9083908690613049565b60008051602061324583398151915261121e8133612086565b61271082111561124157604051637e2df70960e11b815260040160405180910390fd5b600b80549083905560408051828152602081018590527f2956acfe8584fb02384e06c675ee215bf10d55c3de1e6ff9b2f621e8a40c64709101610dfa565b6000805160206132458339815191526112988133612086565b600e805461ff00191690556040517f94482ee2b195c365dbbc2d689fd5a088d2b219abe44360ba8895525c9471d66f90610927903390612e6a565b6000805160206132258339815191526112ec8133612086565b8382811461130d5760405163cc6e40b360e01b815260040160405180910390fd5b60005b8181101561147857600060068189898581811061132f5761132f612f8f565b60209081029290920135835250810191909152604001600020546001600160a01b031603611370576040516305a8a45b60e41b815260040160405180910390fd5b6006600088888481811061138657611386612f8f565b905060200201358152602001908152602001600020600201546000146113bf57604051631139f30960e31b815260040160405180910390fd5b8484828181106113d1576113d1612f8f565b90506020020135600660008989858181106113ee576113ee612f8f565b9050602002013581526020019081526020016000206002018190555084848281811061141c5761141c612f8f565b9050602002013587878381811061143557611435612f8f565b905060200201357fc2055184bbc2d10b90bf7df17a84f8bdda6b52377a976e41e0c1610fffafc0d760405160405180910390a361147181612ffa565b9050611310565b50505050505050565b60008051602061324583398151915261149a8133612086565b600e805460ff191690556040517fc641b9c4afa539cedcbe2e5f3e47d9f092175b5d0b8ae72dffa634a3eb3e47e490610927903390612e6a565b60008281526002602052604081206114ec908361232a565b9392505050565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6000805160206132058339815191526115378133612086565b600e805460ff191660011790556040517f71e0406677c0570b2a66b1a4feeccf5c1cba2d6729435461e27a312b15410d0490610927903390612e6a565b60008051602061322583398151915261158d8133612086565b838281146115ae5760405163cc6e40b360e01b815260040160405180910390fd5b60005b8181101561147857600760008888848181106115cf576115cf612f8f565b9050602002013581526020019081526020016000206002015460001461160857604051631139f30960e31b815260040160405180910390fd5b84848281811061161a5761161a612f8f565b905060200201356007600089898581811061163757611637612f8f565b9050602002013581526020019081526020016000206002018190555084848281811061166557611665612f8f565b9050602002013587878381811061167e5761167e612f8f565b905060200201357e05e86a70f400d1820ab5a0573a2be911d831ab28fe2e9448b34daab223b09c60405160405180910390a36116b981612ffa565b90506115b1565b6000805160206132458339815191526116d98133612086565b6127108210156116fc5760405163617ab12d60e11b815260040160405180910390fd5b600880549083905560408051828152602081018590527fe6e25add7363f8f8a40cbea9810d3115a33703b10972ef759104219b006574369101610dfa565b6000805160206132458339815191526117538133612086565b610fbc82612336565b60008181526002602052604081206108c9906123b0565b7fced4eb9faeb19ab0e2e05a20ade58d82157e1035a3fbff4bc38dd5e609f22b9361179e8133612086565b428410156117bf5760405163209768a360e11b815260040160405180910390fd5b8160005b818110156118515785604460008787858181106117e2576117e2612f8f565b9050602002013581526020019081526020016000208190555084848281811061180d5761180d612f8f565b90506020020135867f15d20a98e8d4b1247fc51e2f6817929874a0769087776e52268eb1b4c8bdb2dd60405160405180910390a361184a81612ffa565b90506117c3565b505050505050565b600082815260016020819052604090912001546118768133612086565b610f3d838361220b565b6002600054036118a25760405162461bcd60e51b815260040161095490612f58565b6002600055600e54610100900460ff1680156118d15760405163aadfaddd60e01b815260040160405180910390fd5b336118db816120ea565b6008548310156118fe57604051636ba4a1c760e01b815260040160405180910390fd5b6000611909846123ba565b905060006119178286612fd4565b600c8054919250600091908261192c83612ffa565b909155506040805160608101825233815260208082018681526000838501818152868252600690935293909320915182546001600160a01b0319166001600160a01b03909116178255915160018201559051600290910155905082156119c8576005546119c8906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169133911686612189565b611a116001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163373bda73a0f13958ee444e0782e1768ab4b76edae2885612189565b6040805187815260208101849052908101849052819033907f7cbce37c7b11d322316420484f40c29ce672ad3fa16752551a3dbe6ccfa04e149060600160405180910390a35050600160005550505050565b600080516020613245833981519152611a7c8133612086565b83611a86816120ea565b6000600660008881526020019081526020016000206040518060600160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201548152505090506040518060600160405280876001600160a01b03168152602001868152602001858152506006600089815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020155905050867f7e506b1f11218d4c947d5a59a97fd996c42afc2b024b6aeaec050930eb2b339982600001518884604001518886602001518b604051610d7d96959493929190613013565b600080516020613245833981519152611bc58133612086565b600f80549083905560408051828152602081018590527f1071422bad736c3651d3d3b7a4eda70e84e9c85a08f21c955d79ded03bbf06bb9101610dfa565b600080516020613245833981519152611c1c8133612086565b600580546001600160a01b038481166001600160a01b0319831681179093556040519116917f15d80a013f22151bc7246e3bc132e12828cde19de98870475e3fa7084015272191610dfa918491613049565b600080516020613245833981519152611c878133612086565b612710821115611caa57604051637e2df70960e11b815260040160405180910390fd5b600a80549083905560408051828152602081018590527f387269377ae17304805d5f88cea4252e5ca47346783c279aeb9e8627335a49ac9101610dfa565b600260005403611d0a5760405162461bcd60e51b815260040161095490612f58565b6002600055600e5460ff168015611d345760405163aadfaddd60e01b815260040160405180910390fd5b600954821015611d575760405163595bd39f60e11b815260040160405180910390fd5b600d805460009182611d6883612ffa565b909155506040805160608101825233808252602080830188815260008486018181528782526007909352859020935184546001600160a01b0319166001600160a01b03918216178555905160018501559051600290930192909255915163079cc67960e41b81529293507f000000000000000000000000000000000000000000000000000000000000000016916379cc679091611e09918790600401613063565b600060405180830381600087803b158015611e2357600080fd5b505af1158015611e37573d6000803e3d6000fd5b50506040518581528392503391507f80ebb30e7c30052bf403a20da869bdd033841684e93930d97c4af74238529b4f9060200160405180910390a35050600160005550565b600260005403611e9e5760405162461bcd60e51b815260040161095490612f58565b6002600055600e5462010000900460ff168015611ece5760405163aadfaddd60e01b815260040160405180910390fd5b600f54831015611ef15760405163595bd39f60e11b815260040160405180910390fd5b600d805460009182611f0283612ffa565b9091555060405163079cc67960e41b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906379cc679090611f579033908890600401613063565b600060405180830381600087803b158015611f7157600080fd5b505af1158015611f85573d6000803e3d6000fd5b505060408051878152602081018790528493503392507fad2102c6abc98f954bd5d61e6c0d19764db331f63019296309309a34f70e66a6910160405180910390a3505060016000555050565b611fdb82826114f3565b610fbc5760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b60006114ec836001600160a01b0384166123cd565b60006001600160e01b03198216637965db0b60e01b14806108c957506301ffc9a760e01b6001600160e01b03198316146108c9565b61209082826114f3565b610fbc576120a8816001600160a01b0316601461241c565b6120b383602061241c565b6040516020016120c49291906130a0565b60408051601f198184030181529082905262461bcd60e51b82526109549160040161310f565b6120f3816125b8565b15612111576040516305ffb90760e11b815260040160405180910390fd5b61211a8161262a565b1561213857604051632be4781160e21b815260040160405180910390fd5b50565b6000806121488385613142565b905061216461215f670de0b6b3a764000083613161565b61265b565b949350505050565b6000612710600b548361217f9190613142565b6108c99190613161565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526121e3908590612687565b50505050565b6121f38282611fd1565b6000828152600260205260409020610f3d908261203c565b6122158282612759565b6000828152600260205260409020610f3d90826127c0565b600081815260446020526040812054900361225b57604051630ad2496160e31b815260040160405180910390fd5b60008181526044602052604090205442101561228a5760405163309b0bcf60e21b815260040160405180910390fd5b612293816127d5565b600090815260446020526040812055565b6001600160a01b0381166122cb576040516310ce5abd60e21b815260040160405180910390fd5b601180546001600160a01b038381166001600160a01b03198316179092556040519116907fa19fd4029e820c57308467576d8d0296f07717cfcb98941cf8988b25dcd700e39061231e9083908590613049565b60405180910390a15050565b60006114ec83836129c9565b6001600160a01b03811661235d57604051637e33865360e01b815260040160405180910390fd5b601080546001600160a01b038381166001600160a01b03198316179092556040519116907f7e053cdc9069fe4f629b6b3fa2a01bb53a9a8305ec11830b259d95e9e75b73049061231e9083908590613049565b60006108c9825490565b6000612710600a548361217f9190613142565b6000818152600183016020526040812054612414575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108c9565b5060006108c9565b6060600061242b836002613142565b612436906002612fe7565b67ffffffffffffffff81111561244e5761244e613183565b6040519080825280601f01601f191660200182016040528015612478576020820181803683370190505b509050600360fc1b8160008151811061249357612493612f8f565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106124c2576124c2612f8f565b60200101906001600160f81b031916908160001a90535060006124e6846002613142565b6124f1906001612fe7565b90505b6001811115612569576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061252557612525612f8f565b1a60f81b82828151811061253b5761253b612f8f565b60200101906001600160f81b031916908160001a90535060049490941c9361256281613199565b90506124f4565b5083156114ec5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610954565b60105460405163fbac395160e01b81526000916001600160a01b03169063fbac3951906125e9908590600401612e6a565b602060405180830381865afa158015612606573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c991906131b0565b60115460405163df592f7d60e01b81526000916001600160a01b03169063df592f7d906125e9908590600401612e6a565b60006108c97f000000000000000000000000000000000000000000000000000000000000000083613161565b60006126dc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166129f39092919063ffffffff16565b805190915015610f3d57808060200190518101906126fa91906131b0565b610f3d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610954565b61276382826114f3565b15610fbc5760008281526001602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006114ec836001600160a01b038416612a02565b6000818152600660209081526040808320815160608101835281546001600160a01b031681526001820154938101939093526002015490820181905290910361283157604051638718c77160e01b815260040160405180910390fd5b6003546040828101519051630e75722360e41b815260048101919091526000916001600160a01b03169063e757223090602401602060405180830381865afa158015612881573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a59190612fa5565b905060006128b7836020015183612af5565b60008581526006602052604080822080546001600160a01b03191681556001810183905560020191909155845190516340c10f1960e01b81529192507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916340c10f1991612932918590600401613063565b600060405180830381600087803b15801561294c57600080fd5b505af1158015612960573d6000803e3d6000fd5b50508451602080870151604080890151815188815293840192909252820187905260608201528793506001600160a01b0390911691507fdd602cc9cb236502fb74f091872b4025184011dd96eee41099caa260842f20249060800160405180910390a350505050565b60008260000182815481106129e0576129e0612f8f565b9060005260206000200154905092915050565b60606121648484600085612b1f565b60008181526001830160205260408120548015612aeb576000612a26600183612fd4565b8554909150600090612a3a90600190612fd4565b9050818114612a9f576000866000018281548110612a5a57612a5a612f8f565b9060005260206000200154905080876000018481548110612a7d57612a7d612f8f565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ab057612ab06131d2565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108c9565b60009150506108c9565b600080612b0184612c50565b612b1390670de0b6b3a7640000613142565b90506121648382613161565b606082471015612b805760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610954565b6001600160a01b0385163b612bd75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610954565b600080866001600160a01b03168587604051612bf391906131e8565b60006040518083038185875af1925050503d8060008114612c30576040519150601f19603f3d011682016040523d82523d6000602084013e612c35565b606091505b5091509150612c45828286612c7c565b979650505050505050565b60006108c97f000000000000000000000000000000000000000000000000000000000000000083613142565b60608315612c8b5750816114ec565b825115612c9b5782518084602001fd5b8160405162461bcd60e51b8152600401610954919061310f565b600060208284031215612cc757600080fd5b81356001600160e01b0319811681146114ec57600080fd5b60008083601f840112612cf157600080fd5b50813567ffffffffffffffff811115612d0957600080fd5b6020830191508360208260051b8501011115612d2457600080fd5b9250929050565b60008060208385031215612d3e57600080fd5b823567ffffffffffffffff811115612d5557600080fd5b612d6185828601612cdf565b90969095509350505050565b600060208284031215612d7f57600080fd5b5035919050565b80356001600160a01b0381168114612d9d57600080fd5b919050565b60008060008060808587031215612db857600080fd5b84359350612dc860208601612d86565b93969395505050506040820135916060013590565b600060208284031215612def57600080fd5b6114ec82612d86565b600080600080600060a08688031215612e1057600080fd5b85359450612e2060208701612d86565b94979496505050506040830135926060810135926080909101359150565b60008060408385031215612e5157600080fd5b82359150612e6160208401612d86565b90509250929050565b6001600160a01b0391909116815260200190565b60008060008060408587031215612e9457600080fd5b843567ffffffffffffffff80821115612eac57600080fd5b612eb888838901612cdf565b90965094506020870135915080821115612ed157600080fd5b50612ede87828801612cdf565b95989497509550505050565b60008060408385031215612efd57600080fd5b50508035926020909101359150565b600080600060408486031215612f2157600080fd5b83359250602084013567ffffffffffffffff811115612f3f57600080fd5b612f4b86828701612cdf565b9497909650939450505050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612fb757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156108c9576108c9612fbe565b808201808211156108c9576108c9612fbe565b60006001820161300c5761300c612fbe565b5060010190565b6001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b60005b8381101561309757818101518382015260200161307f565b50506000910152565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516130d281601785016020880161307c565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161310381602884016020880161307c565b01602801949350505050565b602081526000825180602084015261312e81604085016020870161307c565b601f01601f19169190910160400192915050565b600081600019048311821515161561315c5761315c612fbe565b500290565b60008261317e57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052604160045260246000fd5b6000816131a8576131a8612fbe565b506000190190565b6000602082840312156131c257600080fd5b815180151581146114ec57600080fd5b634e487b7160e01b600052603160045260246000fd5b600082516131fa81846020870161307c565b919091019291505056fe9ac2c43e905fe4f0c030a0b0e4b805a284e79da32a5c9c71be1c68dd79bbb89d830a9081649e91840eb0274e99b47626a896cfa0f4dd591cb31cd5060e566c0d8c6dd8af24db306eb580672d47cf7dd23b8394bf74074f8ac14b948512ecdb03a2646970667358221220e50e8ac686954d12f9ea6160d12a7f72993f15c301125b7b66dd8b7ae8858cb764736f6c634300081000339ac2c43e905fe4f0c030a0b0e4b805a284e79da32a5c9c71be1c68dd79bbb89d8c6dd8af24db306eb580672d47cf7dd23b8394bf74074f8ac14b948512ecdb03000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c0000000000000000000000001a694a09494e214a3be3652e4b343b7b81a73ad70000000000000000000000002e55b738f5969eea10fb67e326bee5e2fa15a2cc0000000000000000000000005eb3ac7d9b8220c484307a2506d611cc759626ca0000000000000000000000001a694a09494e214a3be3652e4b343b7b81a73ad7000000000000000000000000000000000000000000000000000000001dcd650000000000000000000000000000000000000000000000001b1ae4d6e2ef500000000000000000000000000000d8c8174691d936e2c80114ec449037b13421b0a800000000000000000000000040c57923924b5c5c5455c48d93317139addac8fb
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103505760003560e01c80638d044c06116101bf578063d547741f116100fa578063e4107c971161009d578063e4107c97146107f8578063e74b981b1461080b578063ec571c6a1461081e578063eddd0d9c14610831578063ee75d7d414610844578063eeb3c91014610857578063f4a203071461086a578063f80a36d61461089157600080fd5b8063d547741f14610760578063d592d81514610773578063d64e539614610786578063d8dfeb4514610799578063dd45eef6146107c0578063de6afa82146107d3578063e0f486ef146107e6578063e1a45218146107ef57600080fd5b8063aa85c1df11610162578063aa85c1df146106b3578063aab483d6146106c6578063aef18ae7146106d9578063bb13245f146106ec578063bcc7028314610713578063ca15c87314610728578063cd4d0bcf1461073b578063d0c835ce1461074d57600080fd5b80638d044c06146106145780639010d07c1461061c57806391d148541461062f578063926d7d7f1461064257806392bccb801461066957806395e4b25114610671578063a217fddf14610698578063a6138ed9146106a057600080fd5b80633bfa67fe1161028f578063525decd611610232578063525decd6146105585780635d591d681461056b57806373a95ddd146105a45780637dbc1df0146105b1578063837018fa146105c457806385c4e79e146105cc57806387e2d06e146105e15780638a07df1e146105f457600080fd5b80633bfa67fe146104cb5780634565e9ff146104f3578063458f581514610506578063469048401461050f57806349cbbf2a1461052257806349dc5e8d1461052a5780634dfe7af21461053d5780634ef1ccd11461054557600080fd5b8063248a9ca3116102f7578063248a9ca3146103e1578063258492cd1461040557806329390370146104185780632b5eceff1461042b5780632f2ff15d1461043e578063354181f31461045157806336568abe1461045a57806338fed7081461046d57600080fd5b806301ffc9a714610355578063078a6be81461037d57806307bda1bb146103a0578063080c279a146103a957806312589fb5146103b257806313966db5146103bb5780632056aa12146103c4578063244f5acf146103ce575b600080fd5b610368610363366004612cb5565b6108a4565b60405190151581526020015b60405180910390f35b61039260008051602061324583398151915281565b604051908152602001610374565b610392600c5481565b61039260085481565b610392600f5481565b610392600a5481565b6103cc6108cf565b005b6103cc6103dc366004612d2b565b610932565b6103926103ef366004612d6d565b6000908152600160208190526040909120015490565b6103cc610413366004612da2565b610c34565b6103cc610426366004612ddd565b610d8e565b6103cc610439366004612df8565b610e07565b6103cc61044c366004612e3e565b610f16565b610392600d5481565b6103cc610468366004612e3e565b610f42565b6104a661047b366004612d6d565b6007602052600090815260409020805460018201546002909201546001600160a01b03909116919083565b604080516001600160a01b039094168452602084019290925290820152606001610374565b6104e673bda73a0f13958ee444e0782e1768ab4b76edae2881565b6040516103749190612e6a565b6103cc610501366004612d2b565b610fc0565b610392600b5481565b6005546104e6906001600160a01b031681565b6103cc61104e565b6103cc610538366004612ddd565b6110a8565b6103cc6110ca565b6103cc610553366004612d6d565b61111f565b6103cc610566366004612ddd565b611199565b6104a6610579366004612d6d565b6006602052600090815260409020805460018201546002909201546001600160a01b03909116919083565b600e546103689060ff1681565b6103cc6105bf366004612d6d565b611205565b6103cc61127f565b61039260008051602061320583398151915281565b6103cc6105ef366004612e7e565b6112d3565b610392610602366004612d6d565b60446020526000908152604090205481565b6103cc611481565b6104e661062a366004612eea565b6114d4565b61036861063d366004612e3e565b6114f3565b6103927fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc481565b6103cc61151e565b6104e67f00000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c81565b610392600081565b6003546104e6906001600160a01b031681565b6103cc6106c1366004612e7e565b611574565b6103cc6106d4366004612d6d565b6116c0565b6103cc6106e7366004612ddd565b61173a565b6103927f000000000000000000000000000000000000000000000000000000e8d4a5100081565b61039260008051602061322583398151915281565b610392610736366004612d6d565b61175c565b600e5461036890610100900460ff1681565b6103cc61075b366004612f0c565b611773565b6103cc61076e366004612e3e565b611859565b6103cc610781366004612d6d565b611880565b6010546104e6906001600160a01b031681565b6104e67f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b600e546103689062010000900460ff1681565b6103cc6107e1366004612da2565b611a63565b61039260095481565b61039261271081565b6103cc610806366004612d6d565b611bac565b6103cc610819366004612ddd565b611c03565b6011546104e6906001600160a01b031681565b6103cc61083f366004612d6d565b611c6e565b6004546104e6906001600160a01b031681565b6103cc610865366004612d6d565b611ce8565b6103927fced4eb9faeb19ab0e2e05a20ade58d82157e1035a3fbff4bc38dd5e609f22b9381565b6103cc61089f366004612eea565b611e7c565b60006001600160e01b03198216635a05180f60e01b14806108c957506108c982612051565b92915050565b6000805160206132058339815191526108e88133612086565b600e805461ff0019166101001790556040517fcd71257f2998474633e94cfffa045014068f6218ffdca256b6f4aa9d5f15fb8990610927903390612e6a565b60405180910390a150565b60026000540361095d5760405162461bcd60e51b815260040161095490612f58565b60405180910390fd5b6002600055600e5460ff1680156109875760405163aadfaddd60e01b815260040160405180910390fd5b600082815b81811015610be0576000600760008888858181106109ac576109ac612f8f565b60209081029290920135835250818101929092526040908101600020815160608101835281546001600160a01b0316808252600183015494820194909452600290910154918101919091529150610a02906120ea565b8060400151600003610a2757604051638718c77160e01b815260040160405180910390fd5b6003546040828101519051630e75722360e41b815260048101919091526000916001600160a01b03169063e757223090602401602060405180830381865afa158015610a77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9b9190612fa5565b90506000610aad83602001518361213b565b90506000610aba8261216c565b90506000610ac88284612fd4565b9050610ad48289612fe7565b9750600760008c8c89818110610aec57610aec612f8f565b60209081029290920135835250810191909152604001600090812080546001600160a01b031916815560018101829055600201556004548551610b5e916001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881169291169084612189565b8a8a87818110610b7057610b70612f8f565b87516020898101516040805191825281830188905281018a905292029390930135926001600160a01b031691507f35908d59be205275271010c5ea7062a88a2b5fbafe268bb9070550276f0edadd9060600160405180910390a3505050505080610bd990612ffa565b905061098c565b508115610c2857600454600554610c28916001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48811692918116911685612189565b50506001600055505050565b600080516020613245833981519152610c4d8133612086565b83610c57816120ea565b6000600760008881526020019081526020016000206040518060600160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201548152505090506040518060600160405280876001600160a01b03168152602001868152602001858152506007600089815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020155905050867f5a0c55c421ae3aac2379811eca16aaee32b6e64411322b624118d4219b9350a082600001518884604001518886602001518b604051610d7d96959493929190613013565b60405180910390a250505050505050565b600080516020613245833981519152610da78133612086565b600380546001600160a01b038481166001600160a01b03198316179092556040519116907f801352e72ef9b80b3992ccbedf07ab0e133e7da7aaccf0024abf23f4f32eb99a90610dfa9083908690613049565b60405180910390a1505050565b7fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4610e328133612086565b84610e3c816120ea565b6000878152600660205260409020546001600160a01b031615610e7257604051631aeecebf60e21b815260040160405180910390fd5b60408051606080820183526001600160a01b0389811680845260208085018b815260008688018181528f82526006845290889020965187546001600160a01b031916951694909417865551600186015591516002909401939093558351898152908101889052928301869052909189917fc985471d1cb1bb75da0d54fa5ab10f7171e952cefcc0bf4fc7c2546c19d1811f910160405180910390a350505050505050565b60008281526001602081905260409091200154610f338133612086565b610f3d83836121e9565b505050565b6001600160a01b0381163314610fb25760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610954565b610fbc828261220b565b5050565b600260005403610fe25760405162461bcd60e51b815260040161095490612f58565b6002600055600e54610100900460ff1680156110115760405163aadfaddd60e01b815260040160405180910390fd5b8160005b81811015610c285761103e85858381811061103257611032612f8f565b9050602002013561222d565b61104781612ffa565b9050611015565b6000805160206132058339815191526110678133612086565b600e805462ff00001916620100001790556040517fdc41a92196ccc1ab8149c01bc68c2f506b10a7bb5cd2693c9516d176f5381ff490610927903390612e6a565b6000805160206132458339815191526110c18133612086565b610fbc826122a4565b6000805160206132458339815191526110e38133612086565b600e805462ff0000191690556040517f53a8c40fc17c78d38e2c06aa8d2c550c1acbf7b30d087dbda289ab3dd41c235c90610927903390612e6a565b6000805160206132458339815191526111388133612086565b61271082101561115b5760405163617ab12d60e11b815260040160405180910390fd5b600980549083905560408051828152602081018590527ffdaf6ed728cef208e62328a008209556f8281f3062b14dd08aaaa90fa15942119101610dfa565b6000805160206132458339815191526111b28133612086565b600480546001600160a01b038481166001600160a01b03198316179092556040519116907fb09f298b2812193d5ada18beaadd6cb8f12b3640926d99de46e2a65394df829d90610dfa9083908690613049565b60008051602061324583398151915261121e8133612086565b61271082111561124157604051637e2df70960e11b815260040160405180910390fd5b600b80549083905560408051828152602081018590527f2956acfe8584fb02384e06c675ee215bf10d55c3de1e6ff9b2f621e8a40c64709101610dfa565b6000805160206132458339815191526112988133612086565b600e805461ff00191690556040517f94482ee2b195c365dbbc2d689fd5a088d2b219abe44360ba8895525c9471d66f90610927903390612e6a565b6000805160206132258339815191526112ec8133612086565b8382811461130d5760405163cc6e40b360e01b815260040160405180910390fd5b60005b8181101561147857600060068189898581811061132f5761132f612f8f565b60209081029290920135835250810191909152604001600020546001600160a01b031603611370576040516305a8a45b60e41b815260040160405180910390fd5b6006600088888481811061138657611386612f8f565b905060200201358152602001908152602001600020600201546000146113bf57604051631139f30960e31b815260040160405180910390fd5b8484828181106113d1576113d1612f8f565b90506020020135600660008989858181106113ee576113ee612f8f565b9050602002013581526020019081526020016000206002018190555084848281811061141c5761141c612f8f565b9050602002013587878381811061143557611435612f8f565b905060200201357fc2055184bbc2d10b90bf7df17a84f8bdda6b52377a976e41e0c1610fffafc0d760405160405180910390a361147181612ffa565b9050611310565b50505050505050565b60008051602061324583398151915261149a8133612086565b600e805460ff191690556040517fc641b9c4afa539cedcbe2e5f3e47d9f092175b5d0b8ae72dffa634a3eb3e47e490610927903390612e6a565b60008281526002602052604081206114ec908361232a565b9392505050565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6000805160206132058339815191526115378133612086565b600e805460ff191660011790556040517f71e0406677c0570b2a66b1a4feeccf5c1cba2d6729435461e27a312b15410d0490610927903390612e6a565b60008051602061322583398151915261158d8133612086565b838281146115ae5760405163cc6e40b360e01b815260040160405180910390fd5b60005b8181101561147857600760008888848181106115cf576115cf612f8f565b9050602002013581526020019081526020016000206002015460001461160857604051631139f30960e31b815260040160405180910390fd5b84848281811061161a5761161a612f8f565b905060200201356007600089898581811061163757611637612f8f565b9050602002013581526020019081526020016000206002018190555084848281811061166557611665612f8f565b9050602002013587878381811061167e5761167e612f8f565b905060200201357e05e86a70f400d1820ab5a0573a2be911d831ab28fe2e9448b34daab223b09c60405160405180910390a36116b981612ffa565b90506115b1565b6000805160206132458339815191526116d98133612086565b6127108210156116fc5760405163617ab12d60e11b815260040160405180910390fd5b600880549083905560408051828152602081018590527fe6e25add7363f8f8a40cbea9810d3115a33703b10972ef759104219b006574369101610dfa565b6000805160206132458339815191526117538133612086565b610fbc82612336565b60008181526002602052604081206108c9906123b0565b7fced4eb9faeb19ab0e2e05a20ade58d82157e1035a3fbff4bc38dd5e609f22b9361179e8133612086565b428410156117bf5760405163209768a360e11b815260040160405180910390fd5b8160005b818110156118515785604460008787858181106117e2576117e2612f8f565b9050602002013581526020019081526020016000208190555084848281811061180d5761180d612f8f565b90506020020135867f15d20a98e8d4b1247fc51e2f6817929874a0769087776e52268eb1b4c8bdb2dd60405160405180910390a361184a81612ffa565b90506117c3565b505050505050565b600082815260016020819052604090912001546118768133612086565b610f3d838361220b565b6002600054036118a25760405162461bcd60e51b815260040161095490612f58565b6002600055600e54610100900460ff1680156118d15760405163aadfaddd60e01b815260040160405180910390fd5b336118db816120ea565b6008548310156118fe57604051636ba4a1c760e01b815260040160405180910390fd5b6000611909846123ba565b905060006119178286612fd4565b600c8054919250600091908261192c83612ffa565b909155506040805160608101825233815260208082018681526000838501818152868252600690935293909320915182546001600160a01b0319166001600160a01b03909116178255915160018201559051600290910155905082156119c8576005546119c8906001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881169133911686612189565b611a116001600160a01b037f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48163373bda73a0f13958ee444e0782e1768ab4b76edae2885612189565b6040805187815260208101849052908101849052819033907f7cbce37c7b11d322316420484f40c29ce672ad3fa16752551a3dbe6ccfa04e149060600160405180910390a35050600160005550505050565b600080516020613245833981519152611a7c8133612086565b83611a86816120ea565b6000600660008881526020019081526020016000206040518060600160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820154815260200160028201548152505090506040518060600160405280876001600160a01b03168152602001868152602001858152506006600089815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015560408201518160020155905050867f7e506b1f11218d4c947d5a59a97fd996c42afc2b024b6aeaec050930eb2b339982600001518884604001518886602001518b604051610d7d96959493929190613013565b600080516020613245833981519152611bc58133612086565b600f80549083905560408051828152602081018590527f1071422bad736c3651d3d3b7a4eda70e84e9c85a08f21c955d79ded03bbf06bb9101610dfa565b600080516020613245833981519152611c1c8133612086565b600580546001600160a01b038481166001600160a01b0319831681179093556040519116917f15d80a013f22151bc7246e3bc132e12828cde19de98870475e3fa7084015272191610dfa918491613049565b600080516020613245833981519152611c878133612086565b612710821115611caa57604051637e2df70960e11b815260040160405180910390fd5b600a80549083905560408051828152602081018590527f387269377ae17304805d5f88cea4252e5ca47346783c279aeb9e8627335a49ac9101610dfa565b600260005403611d0a5760405162461bcd60e51b815260040161095490612f58565b6002600055600e5460ff168015611d345760405163aadfaddd60e01b815260040160405180910390fd5b600954821015611d575760405163595bd39f60e11b815260040160405180910390fd5b600d805460009182611d6883612ffa565b909155506040805160608101825233808252602080830188815260008486018181528782526007909352859020935184546001600160a01b0319166001600160a01b03918216178555905160018501559051600290930192909255915163079cc67960e41b81529293507f00000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c16916379cc679091611e09918790600401613063565b600060405180830381600087803b158015611e2357600080fd5b505af1158015611e37573d6000803e3d6000fd5b50506040518581528392503391507f80ebb30e7c30052bf403a20da869bdd033841684e93930d97c4af74238529b4f9060200160405180910390a35050600160005550565b600260005403611e9e5760405162461bcd60e51b815260040161095490612f58565b6002600055600e5462010000900460ff168015611ece5760405163aadfaddd60e01b815260040160405180910390fd5b600f54831015611ef15760405163595bd39f60e11b815260040160405180910390fd5b600d805460009182611f0283612ffa565b9091555060405163079cc67960e41b81529091506001600160a01b037f00000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c16906379cc679090611f579033908890600401613063565b600060405180830381600087803b158015611f7157600080fd5b505af1158015611f85573d6000803e3d6000fd5b505060408051878152602081018790528493503392507fad2102c6abc98f954bd5d61e6c0d19764db331f63019296309309a34f70e66a6910160405180910390a3505060016000555050565b611fdb82826114f3565b610fbc5760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b60006114ec836001600160a01b0384166123cd565b60006001600160e01b03198216637965db0b60e01b14806108c957506301ffc9a760e01b6001600160e01b03198316146108c9565b61209082826114f3565b610fbc576120a8816001600160a01b0316601461241c565b6120b383602061241c565b6040516020016120c49291906130a0565b60408051601f198184030181529082905262461bcd60e51b82526109549160040161310f565b6120f3816125b8565b15612111576040516305ffb90760e11b815260040160405180910390fd5b61211a8161262a565b1561213857604051632be4781160e21b815260040160405180910390fd5b50565b6000806121488385613142565b905061216461215f670de0b6b3a764000083613161565b61265b565b949350505050565b6000612710600b548361217f9190613142565b6108c99190613161565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526121e3908590612687565b50505050565b6121f38282611fd1565b6000828152600260205260409020610f3d908261203c565b6122158282612759565b6000828152600260205260409020610f3d90826127c0565b600081815260446020526040812054900361225b57604051630ad2496160e31b815260040160405180910390fd5b60008181526044602052604090205442101561228a5760405163309b0bcf60e21b815260040160405180910390fd5b612293816127d5565b600090815260446020526040812055565b6001600160a01b0381166122cb576040516310ce5abd60e21b815260040160405180910390fd5b601180546001600160a01b038381166001600160a01b03198316179092556040519116907fa19fd4029e820c57308467576d8d0296f07717cfcb98941cf8988b25dcd700e39061231e9083908590613049565b60405180910390a15050565b60006114ec83836129c9565b6001600160a01b03811661235d57604051637e33865360e01b815260040160405180910390fd5b601080546001600160a01b038381166001600160a01b03198316179092556040519116907f7e053cdc9069fe4f629b6b3fa2a01bb53a9a8305ec11830b259d95e9e75b73049061231e9083908590613049565b60006108c9825490565b6000612710600a548361217f9190613142565b6000818152600183016020526040812054612414575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108c9565b5060006108c9565b6060600061242b836002613142565b612436906002612fe7565b67ffffffffffffffff81111561244e5761244e613183565b6040519080825280601f01601f191660200182016040528015612478576020820181803683370190505b509050600360fc1b8160008151811061249357612493612f8f565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106124c2576124c2612f8f565b60200101906001600160f81b031916908160001a90535060006124e6846002613142565b6124f1906001612fe7565b90505b6001811115612569576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061252557612525612f8f565b1a60f81b82828151811061253b5761253b612f8f565b60200101906001600160f81b031916908160001a90535060049490941c9361256281613199565b90506124f4565b5083156114ec5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610954565b60105460405163fbac395160e01b81526000916001600160a01b03169063fbac3951906125e9908590600401612e6a565b602060405180830381865afa158015612606573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c991906131b0565b60115460405163df592f7d60e01b81526000916001600160a01b03169063df592f7d906125e9908590600401612e6a565b60006108c97f000000000000000000000000000000000000000000000000000000e8d4a5100083613161565b60006126dc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166129f39092919063ffffffff16565b805190915015610f3d57808060200190518101906126fa91906131b0565b610f3d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610954565b61276382826114f3565b15610fbc5760008281526001602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006114ec836001600160a01b038416612a02565b6000818152600660209081526040808320815160608101835281546001600160a01b031681526001820154938101939093526002015490820181905290910361283157604051638718c77160e01b815260040160405180910390fd5b6003546040828101519051630e75722360e41b815260048101919091526000916001600160a01b03169063e757223090602401602060405180830381865afa158015612881573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a59190612fa5565b905060006128b7836020015183612af5565b60008581526006602052604080822080546001600160a01b03191681556001810183905560020191909155845190516340c10f1960e01b81529192507f00000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c6001600160a01b0316916340c10f1991612932918590600401613063565b600060405180830381600087803b15801561294c57600080fd5b505af1158015612960573d6000803e3d6000fd5b50508451602080870151604080890151815188815293840192909252820187905260608201528793506001600160a01b0390911691507fdd602cc9cb236502fb74f091872b4025184011dd96eee41099caa260842f20249060800160405180910390a350505050565b60008260000182815481106129e0576129e0612f8f565b9060005260206000200154905092915050565b60606121648484600085612b1f565b60008181526001830160205260408120548015612aeb576000612a26600183612fd4565b8554909150600090612a3a90600190612fd4565b9050818114612a9f576000866000018281548110612a5a57612a5a612f8f565b9060005260206000200154905080876000018481548110612a7d57612a7d612f8f565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ab057612ab06131d2565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108c9565b60009150506108c9565b600080612b0184612c50565b612b1390670de0b6b3a7640000613142565b90506121648382613161565b606082471015612b805760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610954565b6001600160a01b0385163b612bd75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610954565b600080866001600160a01b03168587604051612bf391906131e8565b60006040518083038185875af1925050503d8060008114612c30576040519150601f19603f3d011682016040523d82523d6000602084013e612c35565b606091505b5091509150612c45828286612c7c565b979650505050505050565b60006108c97f000000000000000000000000000000000000000000000000000000e8d4a5100083613142565b60608315612c8b5750816114ec565b825115612c9b5782518084602001fd5b8160405162461bcd60e51b8152600401610954919061310f565b600060208284031215612cc757600080fd5b81356001600160e01b0319811681146114ec57600080fd5b60008083601f840112612cf157600080fd5b50813567ffffffffffffffff811115612d0957600080fd5b6020830191508360208260051b8501011115612d2457600080fd5b9250929050565b60008060208385031215612d3e57600080fd5b823567ffffffffffffffff811115612d5557600080fd5b612d6185828601612cdf565b90969095509350505050565b600060208284031215612d7f57600080fd5b5035919050565b80356001600160a01b0381168114612d9d57600080fd5b919050565b60008060008060808587031215612db857600080fd5b84359350612dc860208601612d86565b93969395505050506040820135916060013590565b600060208284031215612def57600080fd5b6114ec82612d86565b600080600080600060a08688031215612e1057600080fd5b85359450612e2060208701612d86565b94979496505050506040830135926060810135926080909101359150565b60008060408385031215612e5157600080fd5b82359150612e6160208401612d86565b90509250929050565b6001600160a01b0391909116815260200190565b60008060008060408587031215612e9457600080fd5b843567ffffffffffffffff80821115612eac57600080fd5b612eb888838901612cdf565b90965094506020870135915080821115612ed157600080fd5b50612ede87828801612cdf565b95989497509550505050565b60008060408385031215612efd57600080fd5b50508035926020909101359150565b600080600060408486031215612f2157600080fd5b83359250602084013567ffffffffffffffff811115612f3f57600080fd5b612f4b86828701612cdf565b9497909650939450505050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612fb757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156108c9576108c9612fbe565b808201808211156108c9576108c9612fbe565b60006001820161300c5761300c612fbe565b5060010190565b6001600160a01b03968716815294909516602085015260408401929092526060830152608082015260a081019190915260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b60005b8381101561309757818101518382015260200161307f565b50506000910152565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516130d281601785016020880161307c565b7001034b99036b4b9b9b4b733903937b6329607d1b601791840191820152835161310381602884016020880161307c565b01602801949350505050565b602081526000825180602084015261312e81604085016020870161307c565b601f01601f19169190910160400192915050565b600081600019048311821515161561315c5761315c612fbe565b500290565b60008261317e57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052604160045260246000fd5b6000816131a8576131a8612fbe565b506000190190565b6000602082840312156131c257600080fd5b815180151581146114ec57600080fd5b634e487b7160e01b600052603160045260246000fd5b600082516131fa81846020870161307c565b919091019291505056fe9ac2c43e905fe4f0c030a0b0e4b805a284e79da32a5c9c71be1c68dd79bbb89d830a9081649e91840eb0274e99b47626a896cfa0f4dd591cb31cd5060e566c0d8c6dd8af24db306eb580672d47cf7dd23b8394bf74074f8ac14b948512ecdb03a2646970667358221220e50e8ac686954d12f9ea6160d12a7f72993f15c301125b7b66dd8b7ae8858cb764736f6c63430008100033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c0000000000000000000000001a694a09494e214a3be3652e4b343b7b81a73ad70000000000000000000000002e55b738f5969eea10fb67e326bee5e2fa15a2cc0000000000000000000000005eb3ac7d9b8220c484307a2506d611cc759626ca0000000000000000000000001a694a09494e214a3be3652e4b343b7b81a73ad7000000000000000000000000000000000000000000000000000000001dcd650000000000000000000000000000000000000000000000001b1ae4d6e2ef500000000000000000000000000000d8c8174691d936e2c80114ec449037b13421b0a800000000000000000000000040c57923924b5c5c5455c48d93317139addac8fb
-----Decoded View---------------
Arg [0] : _collateral (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [1] : _rwa (address): 0x96F6eF951840721AdBF46Ac996b59E0235CB985C
Arg [2] : managerAdmin (address): 0x1a694A09494E214a3Be3652e4B343B7B81A73ad7
Arg [3] : pauser (address): 0x2e55b738F5969Eea10fB67e326BEE5e2fA15A2CC
Arg [4] : _assetSender (address): 0x5Eb3ac7D9B8220C484307a2506D611Cc759626Ca
Arg [5] : _feeRecipient (address): 0x1a694A09494E214a3Be3652e4B343B7B81A73ad7
Arg [6] : _minimumDepositAmount (uint256): 500000000
Arg [7] : _minimumRedemptionAmount (uint256): 500000000000000000000
Arg [8] : blocklist (address): 0xd8c8174691d936E2C80114EC449037b13421B0a8
Arg [9] : sanctionsList (address): 0x40C57923924B5c5c5455c48D93317139ADDaC8fb
-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [1] : 00000000000000000000000096f6ef951840721adbf46ac996b59e0235cb985c
Arg [2] : 0000000000000000000000001a694a09494e214a3be3652e4b343b7b81a73ad7
Arg [3] : 0000000000000000000000002e55b738f5969eea10fb67e326bee5e2fa15a2cc
Arg [4] : 0000000000000000000000005eb3ac7d9b8220c484307a2506d611cc759626ca
Arg [5] : 0000000000000000000000001a694a09494e214a3be3652e4b343b7b81a73ad7
Arg [6] : 000000000000000000000000000000000000000000000000000000001dcd6500
Arg [7] : 00000000000000000000000000000000000000000000001b1ae4d6e2ef500000
Arg [8] : 000000000000000000000000d8c8174691d936e2c80114ec449037b13421b0a8
Arg [9] : 00000000000000000000000040c57923924b5c5c5455c48d93317139addac8fb
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.