Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x6101c060 | 21988618 | 346 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ERC7540Vault
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 500 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.26;
import {Auth} from "src/Auth.sol";
import {IRoot} from "src/interfaces/IRoot.sol";
import {EIP712Lib} from "src/libraries/EIP712Lib.sol";
import {IRecoverable} from "src/interfaces/IRoot.sol";
import {ITranche} from "src/interfaces/token/ITranche.sol";
import {SignatureLib} from "src/libraries/SignatureLib.sol";
import {SafeTransferLib} from "src/libraries/SafeTransferLib.sol";
import {IInvestmentManager} from "src/interfaces/IInvestmentManager.sol";
import "src/interfaces/IERC7540.sol";
import "src/interfaces/IERC7575.sol";
import "src/interfaces/IERC20.sol";
/// @title ERC7540Vault
/// @notice Asynchronous Tokenized Vault standard implementation for Centrifuge pools
///
/// @dev Each vault issues shares of Centrifuge tranches as restricted ERC-20 tokens
/// against asset deposits based on the current share price.
///
/// ERC-7540 is an extension of the ERC-4626 standard by 'requestDeposit' & 'requestRedeem' methods, where
/// deposit and redeem orders are submitted to the pools to be included in the execution of the following epoch.
/// After execution users can use the deposit, mint, redeem and withdraw functions to get their shares
/// and/or assets from the pools.
contract ERC7540Vault is Auth, IERC7540Vault {
/// @dev Requests for Centrifuge pool are non-fungible and all have ID = 0
uint256 private constant REQUEST_ID = 0;
IRoot public immutable root;
IInvestmentManager public manager;
/// @inheritdoc IERC7540Vault
uint64 public immutable poolId;
/// @inheritdoc IERC7540Vault
bytes16 public immutable trancheId;
/// @inheritdoc IERC7575
address public immutable asset;
/// @inheritdoc IERC7575
address public immutable share;
uint8 internal immutable _shareDecimals;
/// --- ERC7741 ---
bytes32 private immutable nameHash;
bytes32 private immutable versionHash;
uint256 public immutable deploymentChainId;
bytes32 private immutable _DOMAIN_SEPARATOR;
bytes32 public constant AUTHORIZE_OPERATOR_TYPEHASH =
keccak256("AuthorizeOperator(address controller,address operator,bool approved,bytes32 nonce,uint256 deadline)");
/// @inheritdoc IERC7741
mapping(address controller => mapping(bytes32 nonce => bool used)) public authorizations;
/// @inheritdoc IERC7540Operator
mapping(address => mapping(address => bool)) public isOperator;
// --- Events ---
event File(bytes32 indexed what, address data);
constructor(uint64 poolId_, bytes16 trancheId_, address asset_, address share_, address root_, address manager_)
Auth(msg.sender)
{
poolId = poolId_;
trancheId = trancheId_;
asset = asset_;
share = share_;
_shareDecimals = IERC20Metadata(share).decimals();
root = IRoot(root_);
manager = IInvestmentManager(manager_);
nameHash = keccak256(bytes("Centrifuge"));
versionHash = keccak256(bytes("1"));
deploymentChainId = block.chainid;
_DOMAIN_SEPARATOR = EIP712Lib.calculateDomainSeparator(nameHash, versionHash);
}
// --- Administration ---
function file(bytes32 what, address data) external auth {
if (what == "manager") manager = IInvestmentManager(data);
else revert("ERC7540Vault/file-unrecognized-param");
emit File(what, data);
}
/// @inheritdoc IRecoverable
function recoverTokens(address token, address to, uint256 amount) external auth {
SafeTransferLib.safeTransfer(token, to, amount);
}
// --- ERC-7540 methods ---
/// @inheritdoc IERC7540Deposit
function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256) {
require(owner == msg.sender || isOperator[owner][msg.sender], "ERC7540Vault/invalid-owner");
require(IERC20(asset).balanceOf(owner) >= assets, "ERC7540Vault/insufficient-balance");
require(
manager.requestDeposit(address(this), assets, controller, owner, msg.sender),
"ERC7540Vault/request-deposit-failed"
);
SafeTransferLib.safeTransferFrom(asset, owner, manager.escrow(), assets);
emit DepositRequest(controller, owner, REQUEST_ID, msg.sender, assets);
return REQUEST_ID;
}
/// @inheritdoc IERC7540Deposit
function pendingDepositRequest(uint256, address controller) external view returns (uint256 pendingAssets) {
pendingAssets = manager.pendingDepositRequest(address(this), controller);
}
/// @inheritdoc IERC7540Deposit
function claimableDepositRequest(uint256, address controller) external view returns (uint256 claimableAssets) {
claimableAssets = maxDeposit(controller);
}
/// @inheritdoc IERC7540Redeem
function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256) {
require(ITranche(share).balanceOf(owner) >= shares, "ERC7540Vault/insufficient-balance");
// If msg.sender is operator of owner, the transfer is executed as if
// the sender is the owner, to bypass the allowance check
address sender = isOperator[owner][msg.sender] ? owner : msg.sender;
require(
manager.requestRedeem(address(this), shares, controller, owner, sender),
"ERC7540Vault/request-redeem-failed"
);
address escrow = manager.escrow();
try ITranche(share).authTransferFrom(sender, owner, escrow, shares) returns (bool) {}
catch {
// Support tranche tokens that block authTransferFrom. In this case ERC20 approval needs to be set
require(ITranche(share).transferFrom(owner, escrow, shares), "ERC7540Vault/transfer-from-failed");
}
emit RedeemRequest(controller, owner, REQUEST_ID, msg.sender, shares);
return REQUEST_ID;
}
/// @inheritdoc IERC7540Redeem
function pendingRedeemRequest(uint256, address controller) external view returns (uint256 pendingShares) {
pendingShares = manager.pendingRedeemRequest(address(this), controller);
}
/// @inheritdoc IERC7540Redeem
function claimableRedeemRequest(uint256, address controller) external view returns (uint256 claimableShares) {
claimableShares = maxRedeem(controller);
}
// --- Asynchronous cancellation methods ---
/// @inheritdoc IERC7540CancelDeposit
function cancelDepositRequest(uint256, address controller) external {
_validateController(controller);
manager.cancelDepositRequest(address(this), controller, msg.sender);
emit CancelDepositRequest(controller, REQUEST_ID, msg.sender);
}
/// @inheritdoc IERC7540CancelDeposit
function pendingCancelDepositRequest(uint256, address controller) external view returns (bool isPending) {
isPending = manager.pendingCancelDepositRequest(address(this), controller);
}
/// @inheritdoc IERC7540CancelDeposit
function claimableCancelDepositRequest(uint256, address controller)
external
view
returns (uint256 claimableAssets)
{
claimableAssets = manager.claimableCancelDepositRequest(address(this), controller);
}
/// @inheritdoc IERC7540CancelDeposit
function claimCancelDepositRequest(uint256, address receiver, address controller)
external
returns (uint256 assets)
{
_validateController(controller);
assets = manager.claimCancelDepositRequest(address(this), receiver, controller);
emit CancelDepositClaim(controller, receiver, REQUEST_ID, msg.sender, assets);
}
/// @inheritdoc IERC7540CancelRedeem
function cancelRedeemRequest(uint256, address controller) external {
_validateController(controller);
manager.cancelRedeemRequest(address(this), controller, msg.sender);
emit CancelRedeemRequest(controller, REQUEST_ID, msg.sender);
}
/// @inheritdoc IERC7540CancelRedeem
function pendingCancelRedeemRequest(uint256, address controller) external view returns (bool isPending) {
isPending = manager.pendingCancelRedeemRequest(address(this), controller);
}
/// @inheritdoc IERC7540CancelRedeem
function claimableCancelRedeemRequest(uint256, address controller)
external
view
returns (uint256 claimableShares)
{
claimableShares = manager.claimableCancelRedeemRequest(address(this), controller);
}
/// @inheritdoc IERC7540CancelRedeem
function claimCancelRedeemRequest(uint256, address receiver, address controller)
external
returns (uint256 shares)
{
_validateController(controller);
shares = manager.claimCancelRedeemRequest(address(this), receiver, controller);
emit CancelRedeemClaim(controller, receiver, REQUEST_ID, msg.sender, shares);
}
/// @inheritdoc IERC7540Operator
function setOperator(address operator, bool approved) external virtual returns (bool success) {
require(msg.sender != operator, "ERC7540Vault/cannot-set-self-as-operator");
isOperator[msg.sender][operator] = approved;
emit OperatorSet(msg.sender, operator, approved);
success = true;
}
/// @inheritdoc IERC7540Vault
function setEndorsedOperator(address owner, bool approved) external virtual {
require(msg.sender != owner, "ERC7540Vault/cannot-set-self-as-operator");
require(root.endorsed(msg.sender), "ERC7540Vault/not-endorsed");
isOperator[owner][msg.sender] = approved;
emit OperatorSet(owner, msg.sender, approved);
}
/// @inheritdoc IERC7741
function DOMAIN_SEPARATOR() public view returns (bytes32) {
return block.chainid == deploymentChainId
? _DOMAIN_SEPARATOR
: EIP712Lib.calculateDomainSeparator(nameHash, versionHash);
}
/// @inheritdoc IERC7741
function authorizeOperator(
address controller,
address operator,
bool approved,
bytes32 nonce,
uint256 deadline,
bytes memory signature
) external returns (bool success) {
require(controller != operator, "ERC7540Vault/cannot-set-self-as-operator");
require(block.timestamp <= deadline, "ERC7540Vault/expired");
require(!authorizations[controller][nonce], "ERC7540Vault/authorization-used");
authorizations[controller][nonce] = true;
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(abi.encode(AUTHORIZE_OPERATOR_TYPEHASH, controller, operator, approved, nonce, deadline))
)
);
require(SignatureLib.isValidSignature(controller, digest, signature), "ERC7540Vault/invalid-authorization");
isOperator[controller][operator] = approved;
emit OperatorSet(controller, operator, approved);
success = true;
}
/// @inheritdoc IERC7741
function invalidateNonce(bytes32 nonce) external {
authorizations[msg.sender][nonce] = true;
}
// --- ERC165 support ---
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
return interfaceId == type(IERC7540Deposit).interfaceId || interfaceId == type(IERC7540Redeem).interfaceId
|| interfaceId == type(IERC7540Operator).interfaceId || interfaceId == type(IERC7540CancelDeposit).interfaceId
|| interfaceId == type(IERC7540CancelRedeem).interfaceId || interfaceId == type(IERC7575).interfaceId
|| interfaceId == type(IERC7741).interfaceId || interfaceId == type(IERC7714).interfaceId
|| interfaceId == type(IERC165).interfaceId;
}
// --- ERC-4626 methods ---
/// @inheritdoc IERC7575
function totalAssets() external view returns (uint256) {
return convertToAssets(IERC20Metadata(share).totalSupply());
}
/// @inheritdoc IERC7575
/// @notice The calculation is based on the token price from the most recent epoch retrieved from Centrifuge.
/// The actual conversion MAY change between order submission and execution.
function convertToShares(uint256 assets) external view returns (uint256 shares) {
shares = manager.convertToShares(address(this), assets);
}
/// @inheritdoc IERC7575
/// @notice The calculation is based on the token price from the most recent epoch retrieved from Centrifuge.
/// The actual conversion MAY change between order submission and execution.
function convertToAssets(uint256 shares) public view returns (uint256 assets) {
assets = manager.convertToAssets(address(this), shares);
}
/// @inheritdoc IERC7575
function maxDeposit(address controller) public view returns (uint256 maxAssets) {
maxAssets = manager.maxDeposit(address(this), controller);
}
/// @inheritdoc IERC7540Deposit
function deposit(uint256 assets, address receiver, address controller) public returns (uint256 shares) {
_validateController(controller);
shares = manager.deposit(address(this), assets, receiver, controller);
emit Deposit(controller, receiver, assets, shares);
}
/// @inheritdoc IERC7575
/// @notice When claiming deposit requests using deposit(), there can be some precision loss leading to dust.
/// It is recommended to use mint() to claim deposit requests instead.
function deposit(uint256 assets, address receiver) external returns (uint256 shares) {
shares = deposit(assets, receiver, msg.sender);
}
/// @inheritdoc IERC7575
function maxMint(address controller) public view returns (uint256 maxShares) {
maxShares = manager.maxMint(address(this), controller);
}
/// @inheritdoc IERC7540Deposit
function mint(uint256 shares, address receiver, address controller) public returns (uint256 assets) {
_validateController(controller);
assets = manager.mint(address(this), shares, receiver, controller);
emit Deposit(controller, receiver, assets, shares);
}
/// @inheritdoc IERC7575
function mint(uint256 shares, address receiver) external returns (uint256 assets) {
assets = mint(shares, receiver, msg.sender);
}
/// @inheritdoc IERC7575
function maxWithdraw(address controller) external view returns (uint256 maxAssets) {
maxAssets = manager.maxWithdraw(address(this), controller);
}
/// @inheritdoc IERC7575
function withdraw(uint256 assets, address receiver, address controller) external returns (uint256 shares) {
_validateController(controller);
shares = manager.withdraw(address(this), assets, receiver, controller);
emit Withdraw(msg.sender, receiver, controller, assets, shares);
}
/// @inheritdoc IERC7575
function maxRedeem(address controller) public view returns (uint256 maxShares) {
maxShares = manager.maxRedeem(address(this), controller);
}
/// @inheritdoc IERC7575
/// @notice When claiming redemption requests using redeem(), there can be some precision loss leading to dust.
/// It is recommended to use withdraw() to claim redemption requests instead.
function redeem(uint256 shares, address receiver, address controller) external returns (uint256 assets) {
_validateController(controller);
assets = manager.redeem(address(this), shares, receiver, controller);
emit Withdraw(msg.sender, receiver, controller, assets, shares);
}
/// @dev Preview functions for ERC-7540 vaults revert
function previewDeposit(uint256) external pure returns (uint256) {
revert();
}
/// @dev Preview functions for ERC-7540 vaults revert
function previewMint(uint256) external pure returns (uint256) {
revert();
}
/// @dev Preview functions for ERC-7540 vaults revert
function previewWithdraw(uint256) external pure returns (uint256) {
revert();
}
/// @dev Preview functions for ERC-7540 vaults revert
function previewRedeem(uint256) external pure returns (uint256) {
revert();
}
// --- Event emitters ---
/// @inheritdoc IERC7540Vault
function onRedeemRequest(address controller, address owner, uint256 shares) external auth {
emit RedeemRequest(controller, owner, REQUEST_ID, msg.sender, shares);
}
/// @inheritdoc IERC7540Vault
function onDepositClaimable(address controller, uint256 assets, uint256 shares) external auth {
emit DepositClaimable(controller, REQUEST_ID, assets, shares);
}
/// @inheritdoc IERC7540Vault
function onRedeemClaimable(address controller, uint256 assets, uint256 shares) external auth {
emit RedeemClaimable(controller, REQUEST_ID, assets, shares);
}
/// @inheritdoc IERC7540Vault
function onCancelDepositClaimable(address controller, uint256 assets) external auth {
emit CancelDepositClaimable(controller, REQUEST_ID, assets);
}
/// @inheritdoc IERC7540Vault
function onCancelRedeemClaimable(address controller, uint256 shares) external auth {
emit CancelRedeemClaimable(controller, REQUEST_ID, shares);
}
// --- Helpers ---
/// @inheritdoc IERC7540Vault
function pricePerShare() external view returns (uint256) {
return convertToAssets(10 ** _shareDecimals);
}
/// @inheritdoc IERC7540Vault
function priceLastUpdated() external view returns (uint64) {
return manager.priceLastUpdated(address(this));
}
/// @inheritdoc IERC7714
function isPermissioned(address controller) external view returns (bool) {
return ITranche(share).checkTransferRestriction(address(0), controller, 0);
}
/// @notice Ensures msg.sender can operate on behalf of controller.
function _validateController(address controller) internal view {
require(controller == msg.sender || isOperator[controller][msg.sender], "ERC7540Vault/invalid-controller");
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.26;
import {IAuth} from "src/interfaces/IAuth.sol";
/// @title Auth
/// @notice Simple authentication pattern
/// @author Based on code from https://github.com/makerdao/dss
abstract contract Auth is IAuth {
/// @inheritdoc IAuth
mapping(address => uint256) public wards;
constructor(address initialWard) {
wards[initialWard] = 1;
emit Rely(initialWard);
}
/// @dev Check if the msg.sender has permissions
modifier auth() {
require(wards[msg.sender] == 1, "Auth/not-authorized");
_;
}
/// @inheritdoc IAuth
function rely(address user) external auth {
wards[user] = 1;
emit Rely(user);
}
/// @inheritdoc IAuth
function deny(address user) external auth {
wards[user] = 0;
emit Deny(user);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.5.0;
import {IMessageHandler} from "src/interfaces/gateway/IGateway.sol";
interface IRecoverable {
/// @notice Used to recover any ERC-20 token.
/// @dev This method is called only by authorized entities
/// @param token It could be 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
/// to recover locked native ETH or any ERC20 compatible token.
/// @param to Receiver of the funds
/// @param amount Amount to send to the receiver.
function recoverTokens(address token, address to, uint256 amount) external;
}
interface IRoot is IMessageHandler {
// --- Events ---
event File(bytes32 indexed what, uint256 data);
event Pause();
event Unpause();
event ScheduleRely(address indexed target, uint256 indexed scheduledTime);
event CancelRely(address indexed target);
event RelyContract(address indexed target, address indexed user);
event DenyContract(address indexed target, address indexed user);
event RecoverTokens(address indexed target, address indexed token, address indexed to, uint256 amount);
event Endorse(address indexed user);
event Veto(address indexed user);
/// @notice Returns whether the root is paused
function paused() external view returns (bool);
/// @notice Returns the current timelock for adding new wards
function delay() external view returns (uint256);
/// @notice Trusted contracts within the system
function endorsements(address target) external view returns (uint256);
/// @notice Returns when `relyTarget` has passed the timelock
function schedule(address relyTarget) external view returns (uint256 timestamp);
// --- Administration ---
/// @notice Updates a contract parameter
/// @param what Accepts a bytes32 representation of 'delay'
function file(bytes32 what, uint256 data) external;
/// --- Endorsements ---
/// @notice Endorses the `user`
/// @dev Endorsed users are trusted contracts in the system. They are allowed to bypass
/// token restrictions (e.g. the Escrow can automatically receive tranche tokens by being endorsed), and
/// can automatically set operators in ERC-7540 vaults (e.g. the CentrifugeRouter) is always an operator.
function endorse(address user) external;
/// @notice Removes the endorsed user
function veto(address user) external;
/// @notice Returns whether the user is endorsed
function endorsed(address user) external view returns (bool);
// --- Pause management ---
/// @notice Pause any contracts that depend on `Root.paused()`
function pause() external;
/// @notice Unpause any contracts that depend on `Root.paused()`
function unpause() external;
/// --- Timelocked ward management ---
/// @notice Schedule relying a new ward after the delay has passed
function scheduleRely(address target) external;
/// @notice Cancel a pending scheduled rely
function cancelRely(address target) external;
/// @notice Execute a scheduled rely
/// @dev Can be triggered by anyone since the scheduling is protected
function executeScheduledRely(address target) external;
/// --- Incoming message handling ---
function handle(bytes calldata message) external;
/// --- External contract ward management ---
/// @notice Make an address a ward on any contract that Root is a ward on
function relyContract(address target, address user) external;
/// @notice Removes an address as a ward on any contract that Root is a ward on
function denyContract(address target, address user) external;
/// --- Token Recovery ---
/// @notice Allows Governance to recover tokens sent to the wrong contract by mistake
function recoverTokens(address target, address token, address to, uint256 amount) external;
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.26;
/// @title EIP712 Lib
library EIP712Lib {
// keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
bytes32 public constant EIP712_DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
function calculateDomainSeparator(bytes32 nameHash, bytes32 versionHash) internal view returns (bytes32) {
return keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, nameHash, versionHash, block.chainid, address(this)));
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.5.0;
import {IERC20Metadata} from "src/interfaces/IERC20.sol";
import {IERC7575Share} from "src/interfaces/IERC7575.sol";
interface IERC1404 {
/// @notice Detects if a transfer will be reverted and if so returns an appropriate reference code
/// @param from Sending address
/// @param to Receiving address
/// @param value Amount of tokens being transferred
/// @return Code by which to reference message for rejection reasoning
/// @dev Overwrite with your custom transfer restriction logic
function detectTransferRestriction(address from, address to, uint256 value) external view returns (uint8);
/// @notice Returns a human-readable message for a given restriction code
/// @param restrictionCode Identifier for looking up a message
/// @return Text showing the restriction's reasoning
/// @dev Overwrite with your custom message and restrictionCode handling
function messageForTransferRestriction(uint8 restrictionCode) external view returns (string memory);
}
interface ITranche is IERC20Metadata, IERC7575Share, IERC1404 {
// --- Events ---
event File(bytes32 indexed what, address data);
event SetHookData(address indexed user, bytes16 data);
struct Balance {
/// @dev The user balance is limited to uint128. This is safe because the decimals are limited to 18,
/// thus the max balance is 2^128-1 / 10**18 = 3.40 * 10**20. This is also enforced on mint.
uint128 amount;
/// @dev There are 16 bytes that are used to store hook data (e.g. restrictions for users).
bytes16 hookData;
}
// --- Administration ---
/// @notice returns the hook that transfers perform callbacks to
/// @dev MUST comply to `IHook` interface
function hook() external view returns (address);
/// @notice Updates a contract parameter
/// @param what Accepts a bytes32 representation of 'name', 'symbol'
function file(bytes32 what, string memory data) external;
/// @notice Updates a contract parameter
/// @param what Accepts a bytes32 representation of 'hook'
function file(bytes32 what, address data) external;
/// @notice updates the vault for a given `asset`
function updateVault(address asset, address vault_) external;
// --- ERC20 overrides ---
/// @notice returns the 16 byte hook data of the given `user`.
/// @dev Stored in the 128 most significant bits of the user balance
function hookDataOf(address user) external view returns (bytes16);
/// @notice update the 16 byte hook data of the given `user`
function setHookData(address user, bytes16 hookData) external;
/// @notice Function to mint tokens
function mint(address user, uint256 value) external;
/// @notice Function to burn tokens
function burn(address user, uint256 value) external;
/// @notice Checks if the tokens can be transferred given the input values
function checkTransferRestriction(address from, address to, uint256 value) external view returns (bool);
/// @notice Performs an authorized transfer, with `sender` as the given sender.
/// @dev Requires allowance if `sender` != `from`
function authTransferFrom(address sender, address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.26;
interface IERC1271 {
function isValidSignature(bytes32, bytes memory) external view returns (bytes4);
}
/// @title Signature Lib
library SignatureLib {
function isValidSignature(address signer, bytes32 digest, bytes memory signature)
internal
view
returns (bool valid)
{
require(signer != address(0), "SignatureLib/invalid-signer");
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
if (signer == ecrecover(digest, v, r, s)) {
return true;
}
}
if (signer.code.length > 0) {
(bool success, bytes memory result) =
signer.staticcall(abi.encodeCall(IERC1271.isValidSignature, (digest, signature)));
valid =
(success && result.length == 32 && abi.decode(result, (bytes4)) == IERC1271.isValidSignature.selector);
}
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.26;
import {IERC20} from "src/interfaces/IERC20.sol";
/// @title Safe Transfer Lib
/// @author Modified from Uniswap v3 Periphery (libraries/TransferHelper.sol)
library SafeTransferLib {
/// @notice Transfers tokens from the targeted address to the given destination
/// @notice Errors if transfer fails
/// @param token The contract address of the token to be transferred
/// @param from The originating address from which the tokens will be transferred
/// @param to The destination address of the transfer
/// @param value The amount to be transferred
function safeTransferFrom(address token, address from, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(abi.encodeCall(IERC20.transferFrom, (from, to, value)));
require(success && (data.length == 0 || abi.decode(data, (bool))), "SafeTransferLib/safe-transfer-from-failed");
}
/// @notice Transfers tokens from msg.sender to a recipient
/// @dev Errors if transfer fails
/// @param token The contract address of the token which will be transferred
/// @param to The recipient of the transfer
/// @param value The value of the transfer
function safeTransfer(address token, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(abi.encodeCall(IERC20.transfer, (to, value)));
require(success && (data.length == 0 || abi.decode(data, (bool))), "SafeTransferLib/safe-transfer-failed");
}
/// @notice Approves the stipulated contract to spend the given allowance in the given token
/// @dev Errors if approval fails
/// @param token The contract address of the token to be approved
/// @param to The target of the approval
/// @param value The amount of the given token the target will be allowed to spend
function safeApprove(address token, address to, uint256 value) internal {
(bool success, bytes memory data) = token.call(abi.encodeCall(IERC20.approve, (to, value)));
require(success && (data.length == 0 || abi.decode(data, (bool))), "SafeTransferLib/safe-approve-failed");
}
/// @notice Transfers ETH to the recipient address
/// @dev Fails with `STE`
/// @dev Make sure that method that is using this function is protected from reentrancy
/// @param to The destination of the transfer
/// @param value The value to be transferred
function safeTransferETH(address to, uint256 value) internal {
(bool success,) = to.call{value: value}(new bytes(0));
require(success, "SafeTransferLib/safe-transfer-eth-failed");
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.5.0;
import {IMessageHandler} from "src/interfaces/gateway/IGateway.sol";
import {IRecoverable} from "src/interfaces/IRoot.sol";
/// @dev Vault requests and deposit/redeem bookkeeping per user
struct InvestmentState {
/// @dev Shares that can be claimed using `mint()`
uint128 maxMint;
/// @dev Assets that can be claimed using `withdraw()`
uint128 maxWithdraw;
/// @dev Weighted average price of deposits, used to convert maxMint to maxDeposit
uint256 depositPrice;
/// @dev Weighted average price of redemptions, used to convert maxWithdraw to maxRedeem
uint256 redeemPrice;
/// @dev Remaining deposit request in assets
uint128 pendingDepositRequest;
/// @dev Remaining redeem request in shares
uint128 pendingRedeemRequest;
/// @dev Assets that can be claimed using `claimCancelDepositRequest()`
uint128 claimableCancelDepositRequest;
/// @dev Shares that can be claimed using `claimCancelRedeemRequest()`
uint128 claimableCancelRedeemRequest;
/// @dev Indicates whether the depositRequest was requested to be cancelled
bool pendingCancelDepositRequest;
/// @dev Indicates whether the redeemRequest was requested to be cancelled
bool pendingCancelRedeemRequest;
}
interface IInvestmentManager is IMessageHandler, IRecoverable {
// --- Events ---
event File(bytes32 indexed what, address data);
event TriggerRedeemRequest(
uint64 indexed poolId, bytes16 indexed trancheId, address user, address asset, uint128 shares
);
/// @notice Returns the investment state
function investments(address vault, address investor)
external
view
returns (
uint128 maxMint,
uint128 maxWithdraw,
uint256 depositPrice,
uint256 redeemPrice,
uint128 pendingDepositRequest,
uint128 pendingRedeemRequest,
uint128 claimableCancelDepositRequest,
uint128 claimableCancelRedeemRequest,
bool pendingCancelDepositRequest,
bool pendingCancelRedeemRequest
);
/// @notice Address of the escrow
function escrow() external view returns (address);
/// @notice Updates contract parameters of type address.
/// @param what The bytes32 representation of 'gateway' or 'poolManager'.
/// @param data The new contract address.
function file(bytes32 what, address data) external;
// --- Outgoing message handling ---
/// @notice Requests assets deposit. Liquidity pools have to request investments from Centrifuge before
/// shares can be minted. The deposit requests are added to the order book
/// on Centrifuge. Once the next epoch is executed on Centrifuge, vaults can
/// proceed with share payouts in case the order got fulfilled.
/// @dev The assets required to fulfill the deposit request have to be locked and are transferred from the
/// owner to the escrow, even though the share payout can only happen after epoch execution.
/// The receiver becomes the owner of deposit request fulfillment.
function requestDeposit(address vault, uint256 assets, address receiver, address owner, address source)
external
returns (bool);
/// @notice Requests share redemption. Liquidity pools have to request redemptions
/// from Centrifuge before actual asset payouts can be done. The redemption
/// requests are added to the order book on Centrifuge. Once the next epoch is
/// executed on Centrifuge, vaults can proceed with asset payouts
/// in case the order got fulfilled.
/// @dev The shares required to fulfill the redemption request have to be locked and are transferred from the
/// owner to the escrow, even though the asset payout can only happen after epoch execution.
/// The receiver becomes the owner of redeem request fulfillment.
function requestRedeem(address vault, uint256 shares, address receiver, address, /* owner */ address source)
external
returns (bool);
/// @notice Requests the cancellation of a pending deposit request. Liquidity pools have to request the
/// cancellation of outstanding requests from Centrifuge before actual assets can be unlocked and
/// transferred
/// to the owner.
/// While users have outstanding cancellation requests no new deposit requests can be submitted.
/// Once the next epoch is executed on Centrifuge, vaults can proceed with asset payouts
/// if orders could be cancelled successfully.
/// @dev The cancellation request might fail in case the pending deposit order already got fulfilled on
/// Centrifuge.
function cancelDepositRequest(address vault, address owner, address source) external;
/// @notice Requests the cancellation of an pending redeem request. Liquidity pools have to request the
/// cancellation of outstanding requests from Centrifuge before actual shares can be unlocked and
/// transferred to the owner.
/// While users have outstanding cancellation requests no new redeem requests can be submitted (exception:
/// trigger through governance).
/// Once the next epoch is executed on Centrifuge, vaults can proceed with share payouts
/// if the orders could be cancelled successfully.
/// @dev The cancellation request might fail in case the pending redeem order already got fulfilled on
/// Centrifuge.
function cancelRedeemRequest(address vault, address owner, address source) external;
// --- Incoming message handling ---
/// @notice Handle incoming messages from Centrifuge. Parse the function params and forward to the corresponding
/// handler function.
function handle(bytes calldata message) external;
/// @notice Fulfills pending deposit requests after successful epoch execution on Centrifuge.
/// The amount of shares that can be claimed by the user is minted and moved to the escrow contract.
/// The MaxMint bookkeeping value is updated.
/// The request fulfillment can be partial.
/// @dev The shares in the escrow are reserved for the user and are transferred to the user on deposit
/// and mint calls.
function fulfillDepositRequest(
uint64 poolId,
bytes16 trancheId,
address user,
uint128 assetId,
uint128 assets,
uint128 shares
) external;
/// @notice Fulfills pending redeem requests after successful epoch execution on Centrifuge.
/// The amount of redeemed shares is burned. The amount of assets that can be claimed by the user in
/// return is locked in the escrow contract. The MaxWithdraw bookkeeping value is updated.
/// The request fulfillment can be partial.
/// @dev The assets in the escrow are reserved for the user and are transferred to the user on redeem
/// and withdraw calls.
function fulfillRedeemRequest(
uint64 poolId,
bytes16 trancheId,
address user,
uint128 assetId,
uint128 assets,
uint128 shares
) external;
/// @notice Fulfills deposit request cancellation after successful epoch execution on Centrifuge.
/// The amount of assets that can be claimed by the user is locked in the escrow contract.
/// Updates claimableCancelDepositRequest bookkeeping value. The cancellation order execution can be
/// partial.
/// @dev The assets in the escrow are reserved for the user and are transferred to the user during
/// claimCancelDepositRequest calls.
/// `fulfillment` represents the decrease in `pendingDepositRequest`.
/// This is a separate parameter from `assets` since there can be some precision loss when calculating this,
/// which would lead to having dust in the pendingDepositRequest value and
/// never closing out the request even after it is technically fulfilled.
///
/// Example:
/// User deposits 100 units of the vaults underlying asset.
/// - At some point they make cancellation request. The order in which is not guaranteed
/// Both requests arrive at CentrifugeChain. If the cancellation is first then all of the
/// deposited amount will be cancelled.
///
/// - There is the case where the deposit event is first and it gets completely fulfilled then
/// No amount of the deposited asset will be cancelled.
///
/// - There is the case where partially the deposit request is fulfilled. Let's say 40 units.
/// Then the cancel request arrives.
/// The remaining amount of deposited funds which is 60 units will cancelled.
/// There is a scenario where the deposit funds might different from the pool currency so some
/// swapping might happen. Either during this swapping or some fee collection or rounding there will be
/// difference between the actual amount that will be returned to the user.
/// `fulfillment` in this case will be 60 units but assets will be some lower amount because of the
/// aforementioned reasons
/// Let's assume the `asset` is 59. The user will be able to take back these 59 but
/// in order to not let any dust, we use `fulfillment` in our calculations.
///
/// `pendingDepositRequest` not necessary gets zeroed during this cancellation event.
/// When CentrifugeChain process the cancel event on its side, part of the deposit might be fulfilled.
/// In such case the chain will send two messages, one `fulfillDepositRequest` and one
/// `fulfillCancelDepositRequest`. In the example above, given the 100 units
/// deposited, 40 units are fulfilled and 60 can be cancelled.
/// The two messages sent from CentrifugeChain are not guaranteed to arrive in order.
///
/// Assuming first is the `fulfillCancelDepositRequest` the `pendingDepositRequest` here will be reduced to
/// 60 units only. Then the `fulfillCancelDepositRequest` arrives with `fulfillment` 60. This amount is
/// removed from `pendingDepositRequests`. Since there are not more pendingDepositRequest` the
/// `pendingCancelDepositRequest` gets deleted.
///
/// Assuming first the `fulfillCancelDepositRequest` arrives then the `pendingDepositRequest` will be 100.
/// `fulfillment` is 60 so we are left with `pendingDepositRequest` equals to 40 ( 100 - 60 ).
/// Then the second message arrives which is `fulfillDepositRequest`. ( Check `fulfillDepositRequest`
/// implementation for details.)
/// When it arrives the `pendingDepositRequest` is 40 and the assets is 40
/// so there are no more `pendingDepositRequest` and right there the `pendingCancelDepositRequest will be
/// deleted.
function fulfillCancelDepositRequest(
uint64 poolId,
bytes16 trancheId,
address user,
uint128 assetId,
uint128 assets,
uint128 fulfillment
) external;
/// @notice Fulfills redeem request cancellation after successful epoch execution on Centrifuge.
/// The amount of shares that can be claimed by the user is locked in the escrow contract.
/// Updates claimableCancelRedeemRequest bookkeeping value. The cancellation order execution can also be
/// partial.
/// @dev The shares in the escrow are reserved for the user and are transferred to the user during
/// claimCancelRedeemRequest calls.
function fulfillCancelRedeemRequest(uint64 poolId, bytes16 trancheId, address user, uint128 assetId, uint128 shares)
external;
/// @notice Triggers a redeem request on behalf of the user through Centrifuge governance.
/// This function is required for legal/compliance reasons and rare scenarios, like share contract
/// migrations.
/// Once the next epoch is executed on Centrifuge, vaults can proceed with asset payouts in case the orders
/// got fulfilled.
/// @dev The user share amount required to fulfill the redeem request has to be locked in escrow,
/// even though the asset payout can only happen after epoch execution.
function triggerRedeemRequest(uint64 poolId, bytes16 trancheId, address user, uint128 assetId, uint128 shares)
external;
// --- View functions ---
/// @notice Converts the assets value to share decimals.
function convertToShares(address vault, uint256 _assets) external view returns (uint256 shares);
/// @notice Converts the shares value to assets decimals.
function convertToAssets(address vault, uint256 _shares) external view returns (uint256 assets);
/// @notice Returns the max amount of assets based on the unclaimed amount of shares after at least one successful
/// deposit order fulfillment on Centrifuge.
function maxDeposit(address vault, address user) external view returns (uint256);
/// @notice Returns the max amount of shares a user can claim after at least one successful deposit order
/// fulfillment on Centrifuge.
function maxMint(address vault, address user) external view returns (uint256 shares);
/// @notice Returns the max amount of assets a user can claim after at least one successful redeem order fulfillment
/// on Centrifuge.
function maxWithdraw(address vault, address user) external view returns (uint256 assets);
/// @notice Returns the max amount of shares based on the unclaimed number of assets after at least one successful
/// redeem order fulfillment on Centrifuge.
function maxRedeem(address vault, address user) external view returns (uint256 shares);
/// @notice Indicates whether a user has pending deposit requests and returns the total deposit request asset
/// request value.
function pendingDepositRequest(address vault, address user) external view returns (uint256 assets);
/// @notice Indicates whether a user has pending redeem requests and returns the total share request value.
function pendingRedeemRequest(address vault, address user) external view returns (uint256 shares);
/// @notice Indicates whether a user has pending deposit request cancellations.
function pendingCancelDepositRequest(address vault, address user) external view returns (bool isPending);
/// @notice Indicates whether a user has pending redeem request cancellations.
function pendingCancelRedeemRequest(address vault, address user) external view returns (bool isPending);
/// @notice Indicates whether a user has claimable deposit request cancellation and returns the total claim
/// value in assets.
function claimableCancelDepositRequest(address vault, address user) external view returns (uint256 assets);
/// @notice Indicates whether a user has claimable redeem request cancellation and returns the total claim
/// value in shares.
function claimableCancelRedeemRequest(address vault, address user) external view returns (uint256 shares);
/// @notice Returns the timestamp of the last share price update for a vault.
function priceLastUpdated(address vault) external view returns (uint64 lastUpdated);
// --- Vault claim functions ---
/// @notice Processes owner's asset deposit after the epoch has been executed on Centrifuge and the deposit order
/// has been successfully processed (partial fulfillment possible).
/// Shares are transferred from the escrow to the receiver. Amount of shares is computed based of the amount
/// of assets and the owner's share price.
/// @dev The assets required to fulfill the deposit are already locked in escrow upon calling requestDeposit.
/// The shares required to fulfill the deposit have already been minted and transferred to the escrow on
/// fulfillDepositRequest.
/// Receiver has to pass all the share token restrictions in order to receive the shares.
function deposit(address vault, uint256 assets, address receiver, address owner)
external
returns (uint256 shares);
/// @notice Processes owner's share mint after the epoch has been executed on Centrifuge and the deposit order has
/// been successfully processed (partial fulfillment possible).
/// Shares are transferred from the escrow to the receiver. Amount of assets is computed based of the amount
/// of shares and the owner's share price.
/// @dev The assets required to fulfill the mint are already locked in escrow upon calling requestDeposit.
/// The shares required to fulfill the mint have already been minted and transferred to the escrow on
/// fulfillDepositRequest.
/// Receiver has to pass all the share token restrictions in order to receive the shares.
function mint(address vault, uint256 shares, address receiver, address owner) external returns (uint256 assets);
/// @notice Processes owner's share redemption after the epoch has been executed on Centrifuge and the redeem order
/// has been successfully processed (partial fulfillment possible).
/// Assets are transferred from the escrow to the receiver. Amount of assets is computed based of the amount
/// of shares and the owner's share price.
/// @dev The shares required to fulfill the redemption were already locked in escrow on requestRedeem and burned
/// on fulfillRedeemRequest.
/// The assets required to fulfill the redemption have already been reserved in escrow on
/// fulfillRedeemtRequest.
function redeem(address vault, uint256 shares, address receiver, address owner) external returns (uint256 assets);
/// @notice Processes owner's asset withdrawal after the epoch has been executed on Centrifuge and the redeem order
/// has been successfully processed (partial fulfillment possible).
/// Assets are transferred from the escrow to the receiver. Amount of shares is computed based of the amount
/// of shares and the owner's share price.
/// @dev The shares required to fulfill the withdrawal were already locked in escrow on requestRedeem and burned
/// on fulfillRedeemRequest.
/// The assets required to fulfill the withdrawal have already been reserved in escrow on
/// fulfillRedeemtRequest.
function withdraw(address vault, uint256 assets, address receiver, address owner)
external
returns (uint256 shares);
/// @notice Processes owner's deposit request cancellation after the epoch has been executed on Centrifuge and the
/// deposit order cancellation has been successfully processed (partial fulfillment possible).
/// Assets are transferred from the escrow to the receiver.
/// @dev The assets required to fulfill the claim have already been reserved for the owner in escrow on
/// fulfillCancelDepositRequest.
function claimCancelDepositRequest(address vault, address receiver, address owner)
external
returns (uint256 assets);
/// @notice Processes owner's redeem request cancellation after the epoch has been executed on Centrifuge and the
/// redeem order cancellation has been successfully processed (partial fulfillment possible).
/// Shares are transferred from the escrow to the receiver.
/// @dev The shares required to fulfill the claim have already been reserved for the owner in escrow on
/// fulfillCancelRedeemRequest.
/// Receiver has to pass all the share token restrictions in order to receive the shares.
function claimCancelRedeemRequest(address vault, address receiver, address owner)
external
returns (uint256 shares);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.5.0;
import {IERC7575} from "src/interfaces/IERC7575.sol";
import {IRecoverable} from "src/interfaces/IRoot.sol";
interface IERC7540Operator {
/**
* @dev The event emitted when an operator is set.
*
* @param controller The address of the controller.
* @param operator The address of the operator.
* @param approved The approval status.
*/
event OperatorSet(address indexed controller, address indexed operator, bool approved);
/**
* @dev Sets or removes an operator for the caller.
*
* @param operator The address of the operator.
* @param approved The approval status.
* @return Whether the call was executed successfully or not
*/
function setOperator(address operator, bool approved) external returns (bool);
/**
* @dev Returns `true` if the `operator` is approved as an operator for an `controller`.
*
* @param controller The address of the controller.
* @param operator The address of the operator.
* @return status The approval status
*/
function isOperator(address controller, address operator) external view returns (bool status);
}
interface IERC7540Deposit is IERC7540Operator {
event DepositRequest(
address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
);
/**
* @dev Transfers assets from sender into the Vault and submits a Request for asynchronous deposit.
*
* - MUST support ERC-20 approve / transferFrom on asset as a deposit Request flow.
* - MUST revert if all of assets cannot be requested for deposit.
* - owner MUST be msg.sender unless some unspecified explicit approval is given by the caller,
* approval of ERC-20 tokens from owner to sender is NOT enough.
*
* @param assets the amount of deposit assets to transfer from owner
* @param controller the controller of the request who will be able to operate the request
* @param owner the source of the deposit assets
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault's underlying asset token.
*/
function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256 requestId);
/**
* @dev Returns the amount of requested assets in Pending state.
*
* - MUST NOT include any assets in Claimable state for deposit or mint.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
*/
function pendingDepositRequest(uint256 requestId, address controller)
external
view
returns (uint256 pendingAssets);
/**
* @dev Returns the amount of requested assets in Claimable state for the controller to deposit or mint.
*
* - MUST NOT include any assets in Pending state.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
*/
function claimableDepositRequest(uint256 requestId, address controller)
external
view
returns (uint256 claimableAssets);
/**
* @dev Mints shares Vault shares to receiver by claiming the Request of the controller.
*
* - MUST emit the Deposit event.
* - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
*/
function deposit(uint256 assets, address receiver, address controller) external returns (uint256 shares);
/**
* @dev Mints exactly shares Vault shares to receiver by claiming the Request of the controller.
*
* - MUST emit the Deposit event.
* - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
*/
function mint(uint256 shares, address receiver, address controller) external returns (uint256 assets);
}
interface IERC7540Redeem is IERC7540Operator {
event RedeemRequest(
address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
);
/**
* @dev Assumes control of shares from sender into the Vault and submits a Request for asynchronous redeem.
*
* - MUST support a redeem Request flow where the control of shares is taken from sender directly
* where msg.sender has ERC-20 approval over the shares of owner.
* - MUST revert if all of shares cannot be requested for redeem.
*
* @param shares the amount of shares to be redeemed to transfer from owner
* @param controller the controller of the request who will be able to operate the request
* @param owner the source of the shares to be redeemed
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault's share token.
*/
function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256 requestId);
/**
* @dev Returns the amount of requested shares in Pending state.
*
* - MUST NOT include any shares in Claimable state for redeem or withdraw.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
*/
function pendingRedeemRequest(uint256 requestId, address controller)
external
view
returns (uint256 pendingShares);
/**
* @dev Returns the amount of requested shares in Claimable state for the controller to redeem or withdraw.
*
* - MUST NOT include any shares in Pending state for redeem or withdraw.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
*/
function claimableRedeemRequest(uint256 requestId, address controller)
external
view
returns (uint256 claimableShares);
}
interface IERC7540CancelDeposit {
event CancelDepositRequest(address indexed controller, uint256 indexed requestId, address sender);
event CancelDepositClaim(
address indexed controller, address indexed receiver, uint256 indexed requestId, address sender, uint256 assets
);
/**
* @dev Submits a Request for cancelling the pending deposit Request
*
* - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
* approval of ERC-20 tokens from controller to sender is NOT enough.
* - MUST set pendingCancelDepositRequest to `true` for the returned requestId after request
* - MUST increase claimableCancelDepositRequest for the returned requestId after fulfillment
* - SHOULD be claimable using `claimCancelDepositRequest`
* Note: while `pendingCancelDepositRequest` is `true`, `requestDeposit` cannot be called
*/
function cancelDepositRequest(uint256 requestId, address controller) external;
/**
* @dev Returns whether the deposit Request is pending cancelation
*
* - MUST NOT show any variations depending on the caller.
*/
function pendingCancelDepositRequest(uint256 requestId, address controller)
external
view
returns (bool isPending);
/**
* @dev Returns the amount of assets that were canceled from a deposit Request, and can now be claimed.
*
* - MUST NOT show any variations depending on the caller.
*/
function claimableCancelDepositRequest(uint256 requestId, address controller)
external
view
returns (uint256 claimableAssets);
/**
* @dev Claims the canceled deposit assets, and removes the pending cancelation Request
*
* - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
* approval of ERC-20 tokens from controller to sender is NOT enough.
* - MUST set pendingCancelDepositRequest to `false` for the returned requestId after request
* - MUST set claimableCancelDepositRequest to 0 for the returned requestId after fulfillment
*/
function claimCancelDepositRequest(uint256 requestId, address receiver, address controller)
external
returns (uint256 assets);
}
interface IERC7540CancelRedeem {
event CancelRedeemRequest(address indexed controller, uint256 indexed requestId, address sender);
event CancelRedeemClaim(
address indexed controller, address indexed receiver, uint256 indexed requestId, address sender, uint256 shares
);
/**
* @dev Submits a Request for cancelling the pending redeem Request
*
* - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
* approval of ERC-20 tokens from controller to sender is NOT enough.
* - MUST set pendingCancelRedeemRequest to `true` for the returned requestId after request
* - MUST increase claimableCancelRedeemRequest for the returned requestId after fulfillment
* - SHOULD be claimable using `claimCancelRedeemRequest`
* Note: while `pendingCancelRedeemRequest` is `true`, `requestRedeem` cannot be called
*/
function cancelRedeemRequest(uint256 requestId, address controller) external;
/**
* @dev Returns whether the redeem Request is pending cancelation
*
* - MUST NOT show any variations depending on the caller.
*/
function pendingCancelRedeemRequest(uint256 requestId, address controller) external view returns (bool isPending);
/**
* @dev Returns the amount of shares that were canceled from a redeem Request, and can now be claimed.
*
* - MUST NOT show any variations depending on the caller.
*/
function claimableCancelRedeemRequest(uint256 requestId, address controller)
external
view
returns (uint256 claimableShares);
/**
* @dev Claims the canceled redeem shares, and removes the pending cancelation Request
*
* - controller MUST be msg.sender unless some unspecified explicit approval is given by the caller,
* approval of ERC-20 tokens from controller to sender is NOT enough.
* - MUST set pendingCancelRedeemRequest to `false` for the returned requestId after request
* - MUST set claimableCancelRedeemRequest to 0 for the returned requestId after fulfillment
*/
function claimCancelRedeemRequest(uint256 requestId, address receiver, address controller)
external
returns (uint256 shares);
}
interface IERC7741 {
/**
* @dev Grants or revokes permissions for `operator` to manage Requests on behalf of the
* `msg.sender`, using an [EIP-712](./eip-712.md) signature.
*/
function authorizeOperator(
address controller,
address operator,
bool approved,
bytes32 nonce,
uint256 deadline,
bytes memory signature
) external returns (bool);
/**
* @dev Revokes the given `nonce` for `msg.sender` as the `owner`.
*/
function invalidateNonce(bytes32 nonce) external;
/**
* @dev Returns whether the given `nonce` has been used for the `controller`.
*/
function authorizations(address controller, bytes32 nonce) external view returns (bool used);
/**
* @dev Returns the `DOMAIN_SEPARATOR` as defined according to EIP-712. The `DOMAIN_SEPARATOR
* should be unique to the contract and chain to prevent replay attacks from other domains,
* and satisfy the requirements of EIP-712, but is otherwise unconstrained.
*/
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
interface IERC7714 {
/**
* @dev Returns `true` if the `user` is permissioned to interact with the contract.
*/
function isPermissioned(address controller) external view returns (bool);
}
/**
* @title IERC7540Vault
* @dev This is the specific set of interfaces used by the Centrifuge impelmentation of ERC7540,
* as a fully asynchronous Vault, with cancelation support, and authorize operator signature support.
*/
interface IERC7540Vault is
IERC7540Deposit,
IERC7540Redeem,
IERC7540CancelDeposit,
IERC7540CancelRedeem,
IERC7575,
IERC7741,
IERC7714,
IRecoverable
{
event DepositClaimable(address indexed controller, uint256 indexed requestId, uint256 assets, uint256 shares);
event RedeemClaimable(address indexed controller, uint256 indexed requestId, uint256 assets, uint256 shares);
event CancelDepositClaimable(address indexed controller, uint256 indexed requestId, uint256 assets);
event CancelRedeemClaimable(address indexed controller, uint256 indexed requestId, uint256 shares);
/// @notice Identifier of the Centrifuge pool
function poolId() external view returns (uint64);
/// @notice Identifier of the tranche of the Centrifuge pool
function trancheId() external view returns (bytes16);
/// @notice Set msg.sender as operator of owner, to `approved` status
/// @dev MUST be called by endorsed sender
function setEndorsedOperator(address owner, bool approved) external;
/// @notice Callback when a redeem Request is triggered externally;
function onRedeemRequest(address controller, address owner, uint256 shares) external;
/// @notice Callback when a deposit Request becomes claimable
function onDepositClaimable(address owner, uint256 assets, uint256 shares) external;
/// @notice Callback when a redeem Request becomes claimable
function onRedeemClaimable(address owner, uint256 assets, uint256 shares) external;
/// @notice Callback when a claim deposit Request becomes claimable
function onCancelDepositClaimable(address owner, uint256 assets) external;
/// @notice Callback when a claim redeem Request becomes claimable
function onCancelRedeemClaimable(address owner, uint256 shares) external;
/// @notice Price of 1 unit of share, quoted in the decimals of the asset.
function pricePerShare() external view returns (uint256);
/// @notice Returns timestamp of the last share price update.
function priceLastUpdated() external view returns (uint64);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.5.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.
*/
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);
}
interface IERC7575 is IERC165 {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the address of the share token
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function share() external view returns (address shareTokenAddress);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}
interface IERC7575Share is IERC165 {
event VaultUpdate(address indexed asset, address vault);
/**
* @dev Returns the address of the Vault for the given asset.
*
* @param asset the ERC-20 token to deposit with into the Vault
*/
function vault(address asset) external view returns (address);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.5.0;
/// @title IERC20
/// @dev Interface of the ERC20 standard as defined in the EIP.
/// @author Modified from OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
interface IERC20 {
/**
* @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);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` 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 value) external returns (bool);
}
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*/
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);
}
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
interface IERC20Wrapper {
/**
* @dev Returns the address of the underlying ERC-20 token that is being wrapped.
*/
function underlying() external view returns (address);
/**
* @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.
*/
function depositFor(address account, uint256 value) external returns (bool);
/**
* @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.
*/
function withdrawTo(address account, uint256 value) external returns (bool);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.5.0;
interface IAuth {
event Rely(address indexed user);
event Deny(address indexed user);
/// @notice Returns whether the target is a ward (has admin access)
function wards(address target) external view returns (uint256);
/// @notice Make user a ward (give them admin access)
function rely(address user) external;
/// @notice Remove user as a ward (remove admin access)
function deny(address user) external;
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.26;
uint8 constant MAX_ADAPTER_COUNT = 8;
interface IGateway {
/// @dev Each adapter struct is packed with the quorum to reduce SLOADs on handle
struct Adapter {
/// @notice Starts at 1 and maps to id - 1 as the index on the adapters array
uint8 id;
/// @notice Number of votes required for a message to be executed
uint8 quorum;
/// @notice Each time the quorum is decreased, a new session starts which invalidates old votes
uint64 activeSessionId;
}
struct Message {
/// @dev Counts are stored as integers (instead of boolean values) to accommodate duplicate
/// messages (e.g. two investments from the same user with the same amount) being
/// processed in parallel. The entire struct is packed in a single bytes32 slot.
/// Max uint16 = 65,535 so at most 65,535 duplicate messages can be processed in parallel.
uint16[MAX_ADAPTER_COUNT] votes;
/// @notice Each time adapters are updated, a new session starts which invalidates old votes
uint64 sessionId;
bytes pendingMessage;
}
// --- Events ---
event ProcessMessage(bytes message, address adapter);
event ProcessProof(bytes32 messageHash, address adapter);
event ExecuteMessage(bytes message, address adapter);
event SendMessage(bytes message);
event RecoverMessage(address adapter, bytes message);
event RecoverProof(address adapter, bytes32 messageHash);
event InitiateMessageRecovery(bytes32 messageHash, address adapter);
event DisputeMessageRecovery(bytes32 messageHash, address adapter);
event ExecuteMessageRecovery(bytes message, address adapter);
event File(bytes32 indexed what, address[] adapters);
event File(bytes32 indexed what, address instance);
event File(bytes32 indexed what, uint8 messageId, address manager);
event File(bytes32 indexed what, address caller, bool isAllowed);
event ReceiveNativeTokens(address indexed sender, uint256 amount);
/// @notice Returns the address of the adapter at the given id.
function adapters(uint256 id) external view returns (address);
/// @notice Returns the address of the contract that handles the given message id.
function messageHandlers(uint8 messageId) external view returns (address);
/// @notice Returns the timestamp when the given recovery can be executed.
function recoveries(address adapter, bytes32 messageHash) external view returns (uint256 timestamp);
// --- Administration ---
/// @notice Used to update an array of addresses ( state variable ) on very rare occasions.
/// @dev Currently it is used to update the supported adapters.
/// @param what The name of the variable to be updated.
/// @param value New addresses.
function file(bytes32 what, address[] calldata value) external;
/// @notice Used to update an address ( state variable ) on very rare occasions.
/// @dev Currently used to update addresses of contract instances.
/// @param what The name of the variable to be updated.
/// @param data New address.
function file(bytes32 what, address data) external;
/// @notice Used to update a mapping ( state variables ) on very rare occasions.
/// @dev Currently used to update any custom handlers for a specific message type.
/// data1 is the message id from MessagesLib.Call and data2 could be any
/// custom instance of a contract that will handle that call.
/// @param what The name of the variable to be updated.
/// @param data1 The key of the mapping.
/// @param data2 The value of the mapping
function file(bytes32 what, uint8 data1, address data2) external;
/// @notice Used to update a mapping ( state variables ) on very rare occasions.
/// @dev Manages who is allowed to call `this.topUp`
///
/// @param what The name of the variable to be updated - `payers`
/// @param caller Address of the payer allowed to top-up
/// @param isAllower Whether the `caller` is allowed to top-up or not
function file(bytes32 what, address caller, bool isAllower) external;
// --- Incoming ---
/// @notice Handles incoming messages, proofs, and recoveries.
/// @dev Assumes adapters ensure messages cannot be confirmed more than once.
/// @param payload Incoming message from the Centrifuge Chain passed through adapters.
function handle(bytes calldata payload) external;
/// @notice Governance on Centrifuge Chain can initiate message recovery. After the challenge period,
/// the recovery can be executed. If a malign adapter initiates message recovery, governance on
/// Centrifuge Chain can dispute and immediately cancel the recovery, using any other valid adapter.
/// @param adapter Adapter that the recovery was targeting
/// @param messageHash Hash of the message being disputed
function disputeMessageRecovery(address adapter, bytes32 messageHash) external;
/// @notice Governance on Centrifuge Chain can initiate message recovery. After the challenge period,
/// the recovery can be executed. If a malign adapter initiates message recovery, governance on
/// Centrifuge Chain can dispute and immediately cancel the recovery, using any other valid adapter.
///
/// Only 1 recovery can be outstanding per message hash. If multiple adapters fail at the same time,
/// these will need to be recovered serially (increasing the challenge period for each failed adapter).
/// @param adapter Adapter's address that the recovery is targeting
/// @param message Hash of the message to be recovered
function executeMessageRecovery(address adapter, bytes calldata message) external;
// --- Outgoing ---
/// @notice Sends outgoing messages to the Centrifuge Chain.
/// @dev Sends 1 message to the first adapter with the full message,
/// and n-1 messages to the other adapters with proofs (hash of message).
/// This ensures message uniqueness (can only be executed on the destination once).
/// Source could be either Centrifuge router or EoA or any contract
/// that calls the ERC7540Vault contract directly.
/// @param message Message to be send. Either the message itself or a hash value of it ( proof ).
/// @param source Entry point of the transaction.
/// Used to determine whether it is eligible for TX cost payment.
function send(bytes calldata message, address source) external payable;
/// @notice Prepays for the TX cost for sending through the adapters
/// and Centrifuge Chain
/// @dev It can be called only through endorsed contracts.
/// Currently being called from Centrifuge Router only.
/// In order to prepay, the method MUST be called with `msg.value`.
/// Called is assumed to have called IGateway.estimate before calling this.
function topUp() external payable;
// --- Helpers ---
/// @notice A view method of the current quorum.abi
/// @dev Quorum shows the amount of votes needed in order for a message to be dispatched further.
/// The quorum is taken from the first adapter.
/// Current quorum is the amount of all adapters.
/// return Needed amount
function quorum() external view returns (uint8);
/// @notice Gets the current active routers session id.
/// @dev When the adapters are updated with new ones,
/// each new set of adapters has their own sessionId.
/// Currently it uses sessionId of the previous set and
/// increments it by 1. The idea of an activeSessionId is
/// to invalidate any incoming messages from previously used adapters.
function activeSessionId() external view returns (uint64);
/// @notice Counts how many times each incoming messages has been received per adapter.
/// @dev It supports parallel messages ( duplicates ). That means that the incoming messages could be
/// the result of two or more independ request from the user of the same type.
/// i.e. Same user would like to deposit same underlying asset with the same amount more then once.
/// @param messageHash The hash value of the incoming message.
function votes(bytes32 messageHash) external view returns (uint16[MAX_ADAPTER_COUNT] memory);
/// @notice Used to calculate overall cost for bridging a payload on the first adapter and settling
/// on the destination chain and bridging its payload proofs on n-1 adapter
/// and settling on the destination chain.
/// @param payload Used in gas cost calculations.
/// @dev Currenly the payload is not taken into consideration.
/// @return perAdapter An array of cost values per adapter. Each value is how much it's going to cost
/// for a message / proof to be passed through one router and executed on Centrifuge Chain
/// @return total Total cost for sending one message and corresponding proofs on through all adapters
function estimate(bytes calldata payload) external view returns (uint256[] memory perAdapter, uint256 total);
/// @notice Used to check current state of the `caller` and whether they are allowed to call
/// `this.topUp` or not.
/// @param caller Address to check
/// @return isAllowed Whether the `caller` `isAllowed to call `this.topUp()`
function payers(address caller) external view returns (bool isAllowed);
}
interface IMessageHandler {
/// @notice Handling incoming messages from Centrifuge Chain.
/// @param message Incoming message
function handle(bytes memory message) external;
}{
"remappings": [
"forge-std/=lib/forge-std/src/",
"@chimera/=lib/chimera/src/",
"chimera/=lib/chimera/src/",
"ds-test/=lib/chimera/lib/forge-std/lib/ds-test/src/",
"forge-gas-snapshot/=lib/forge-gas-snapshot/src/"
],
"optimizer": {
"enabled": true,
"runs": 500
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint64","name":"poolId_","type":"uint64"},{"internalType":"bytes16","name":"trancheId_","type":"bytes16"},{"internalType":"address","name":"asset_","type":"address"},{"internalType":"address","name":"share_","type":"address"},{"internalType":"address","name":"root_","type":"address"},{"internalType":"address","name":"manager_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"CancelDepositClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"CancelDepositClaimable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"CancelDepositRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"CancelRedeemClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"CancelRedeemClaimable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"CancelRedeemRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Deny","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"DepositClaimable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"DepositRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"what","type":"bytes32"},{"indexed":false,"internalType":"address","name":"data","type":"address"}],"name":"File","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"OperatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"RedeemClaimable","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"controller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"RedeemRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Rely","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"AUTHORIZE_OPERATOR_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"},{"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"authorizations","outputs":[{"internalType":"bool","name":"used","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"},{"internalType":"bytes32","name":"nonce","type":"bytes32"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"authorizeOperator","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"cancelDepositRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"cancelRedeemRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"controller","type":"address"}],"name":"claimCancelDepositRequest","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"controller","type":"address"}],"name":"claimCancelRedeemRequest","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"claimableCancelDepositRequest","outputs":[{"internalType":"uint256","name":"claimableAssets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"claimableCancelRedeemRequest","outputs":[{"internalType":"uint256","name":"claimableShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"claimableDepositRequest","outputs":[{"internalType":"uint256","name":"claimableAssets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"claimableRedeemRequest","outputs":[{"internalType":"uint256","name":"claimableShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"deny","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deploymentChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"controller","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"what","type":"bytes32"},{"internalType":"address","name":"data","type":"address"}],"name":"file","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"invalidateNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"isPermissioned","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"contract IInvestmentManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"maxAssets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"maxShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"maxShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"maxAssets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"controller","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"},{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"onCancelDepositClaimable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"onCancelRedeemClaimable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"},{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"onDepositClaimable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"},{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"onRedeemClaimable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"onRedeemRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"pendingCancelDepositRequest","outputs":[{"internalType":"bool","name":"isPending","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"pendingCancelRedeemRequest","outputs":[{"internalType":"bool","name":"isPending","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"pendingDepositRequest","outputs":[{"internalType":"uint256","name":"pendingAssets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"controller","type":"address"}],"name":"pendingRedeemRequest","outputs":[{"internalType":"uint256","name":"pendingShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"priceLastUpdated","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricePerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"controller","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rely","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"controller","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"requestDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"controller","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"requestRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"root","outputs":[{"internalType":"contract IRoot","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setEndorsedOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setOperator","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"share","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trancheId","outputs":[{"internalType":"bytes16","name":"","type":"bytes16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"controller","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101c0604052348015610010575f80fd5b506040516136de3803806136de83398101604081905261002f91610241565b335f81815260208190526040808220600190555182917fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a6091a2506001600160401b03861660a0526001600160801b0319851660c0526001600160a01b0380851660e05283166101008190526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa1580156100d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100f791906102cd565b60ff16610120526001600160a01b03828116608052600180546001600160a01b031916918316919091178155604080518082018252600a81526943656e7472696675676560b01b6020918201527fe416b338a274162320c79445ae6604141d1cb08275eb27011b69f002dc094d056101409081528251808401909352928252603160f81b9101527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66101608190524661018052905161021691604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020820152908101839052606081018290524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905092915050565b6101a052506102f4945050505050565b80516001600160a01b038116811461023c575f80fd5b919050565b5f805f805f8060c08789031215610256575f80fd5b86516001600160401b038116811461026c575f80fd5b60208801519096506001600160801b031981168114610289575f80fd5b945061029760408801610226565b93506102a560608801610226565b92506102b360808801610226565b91506102c160a08801610226565b90509295509295509295565b5f602082840312156102dd575f80fd5b815160ff811681146102ed575f80fd5b9392505050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a05161333c6103a25f395f61119d01525f818161080901526110d101525f61114c01525f61112701525f6121d701525f81816106c8015281816109e5015281816118c7015281816119c801528181611c420152611cda01525f81816104e301528181611f2e01526120d401525f61075501525f61052201525f81816108bc0152610cf0015261333c5ff3fe608060405234801561000f575f80fd5b5060043610610392575f3560e01c806384ce2bf7116101df578063ba08765211610109578063d4e8be83116100a9578063ebf0c71711610079578063ebf0c717146108b7578063ef8b30f71461040f578063f15b65b1146108de578063f5a23d8d146108f1575f80fd5b8063d4e8be831461086b578063d905777e1461087e578063da39b3e714610891578063eaed1d07146108a4575f80fd5b8063c6e6f592116100e4578063c6e6f592146107f1578063cd0d009614610804578063cdf5bba31461082b578063ce96cb7714610858575f80fd5b8063ba087652146107ac578063bf353dbb146107bf578063c63d75b6146107de575f80fd5b8063a8d5fd651161017f578063b460af941161014f578063b460af9414610710578063b6363cf214610723578063b7adb4c514610750578063b9cf063414610799575f80fd5b8063a8d5fd65146106c3578063aabb5922146106ea578063b04a5e05146106fd578063b3d7f6b91461040f575f80fd5b806399530b06116101ba57806399530b0614610682578063995ea21a1461068a5780639c52a7f11461069d578063a21ec79f146106b0575f80fd5b806384ce2bf71461064957806385b77f451461065c57806394bf804d1461066f575f80fd5b80633e0dc34e116102c05780635f3e849f11610260578063711b58ff11610230578063711b58ff146105fd57806378d77ecb146106105780637c1b50c4146106235780637d41c86e14610636575f80fd5b80635f3e849f146105b157806365fae35e146105c457806369d77a44146105d75780636e553f65146105ea575f80fd5b80634b5fd6661161029b5780634b5fd666146105835780634cdad5061461040f57806352aaead814610596578063558a72971461059e575f80fd5b80633e0dc34e1461051d578063402d267d1461055d578063481c6a7514610570575f80fd5b806321f075ee116103365780632cdfbae5116103065780632cdfbae5146104b05780632e2d2984146104c35780633644e515146104d657806338d52e0f146104de575f80fd5b806321f075ee14610444578063234f0e3b1461045757806326c6f96c1461048a5780632b9d9c1f1461049d575f80fd5b80630263704b116103715780630263704b146103e757806307a2d13a146103fc5780630a28a4771461040f5780630d62c3321461041d575f80fd5b8062a06d191461039657806301e1d114146103bc57806301ffc9a7146103c4575b5f80fd5b6103a96103a4366004612e43565b610904565b6040519081526020015b60405180910390f35b6103a96109df565b6103d76103d2366004612e97565b610a68565b60405190151581526020016103b3565b6103fa6103f5366004612eb2565b610b5b565b005b6103a961040a366004612ee4565b610c00565b6103a9610392366004612ee4565b6103a97fa3efcf8cb518126a85cdfd1c1102ee539e0700189f80926e1ac37144450473fa81565b6103fa610452366004612f08565b610c72565b6103fa610465366004612ee4565b335f90815260026020908152604080832093835292905220805460ff19166001179055565b6103a9610498366004612f3f565b610e19565b6103fa6104ab366004612f3f565b610e93565b6103fa6104be366004612f62565b610f3f565b6103a96104d1366004612e43565b610fe3565b6103a96110ce565b6105057f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103b3565b6105447f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff90911681526020016103b3565b6103a961056b366004612fa0565b6111bf565b600154610505906001600160a01b031681565b6103fa610591366004612fbb565b6111f7565b610544611287565b6103d76105ac366004612f08565b6112f1565b6103fa6105bf366004612f62565b6113cb565b6103fa6105d2366004612fa0565b61142f565b6103a96105e5366004612e43565b6114c7565b6103a96105f8366004612f3f565b611597565b6103d761060b366004612ff9565b6115a3565b6103d761061e366004612fa0565b611897565b6103d7610631366004612f3f565b611932565b6103a9610644366004612e43565b6119a5565b6103fa610657366004612fbb565b611df7565b6103a961066a366004612e43565b611e87565b6103a961067d366004612f3f565b6121c2565b6103a96121ce565b6103a9610698366004612f3f565b6121fd565b6103fa6106ab366004612fa0565b612207565b6103fa6106be366004612eb2565b61229e565b6105057f000000000000000000000000000000000000000000000000000000000000000081565b6103a96106f8366004612f3f565b612335565b6103a961070b366004612f3f565b61236d565b6103a961071e366004612e43565b6123a5565b6103d76107313660046130f4565b600360209081525f928352604080842090915290825290205460ff1681565b6107777f000000000000000000000000000000000000000000000000000000000000000081565b6040516fffffffffffffffffffffffffffffffff1990911681526020016103b3565b6103fa6107a7366004612f3f565b61248b565b6103a96107ba366004612e43565b612537565b6103a96107cd366004612fa0565b5f6020819052908152604090205481565b6103a96107ec366004612fa0565b61261d565b6103a96107ff366004612ee4565b612655565b6103a97f000000000000000000000000000000000000000000000000000000000000000081565b6103d7610839366004612fbb565b600260209081525f928352604080842090915290825290205460ff1681565b6103a9610866366004612fa0565b61268c565b6103fa610879366004612f3f565b6126c4565b6103a961088c366004612fa0565b6127ec565b6103a961089f366004612e43565b612824565b6103a96108b2366004612f3f565b612900565b6105057f000000000000000000000000000000000000000000000000000000000000000081565b6103d76108ec366004612f3f565b61290a565b6103a96108ff366004612f3f565b612942565b5f61090e8261297a565b6001546040516311dcd79160e01b81523060048201526001600160a01b0385811660248301528481166044830152909116906311dcd791906064016020604051808303815f875af1158015610965573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109899190613120565b60408051338152602081018390529192505f916001600160a01b0380871692908616917f9c133d4657dc9cd12f4c08cef86ef778dbbe03f3ad3b661ff14d36bc3febb1fb91015b60405180910390a49392505050565b5f610a637f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a3f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061040a9190613120565b905090565b5f6001600160e01b03198216630ce3bbe560e41b1480610a9857506001600160e01b03198216631883ba3960e21b145b80610ab357506001600160e01b0319821663e3bc4e6560e01b145b80610ace57506001600160e01b03198216638bf840e360e01b145b80610ae957506001600160e01b0319821663e76cffc760e01b145b80610b0457506001600160e01b03198216632f0a18c560e01b145b80610b1f57506001600160e01b031982166354f2843960e11b145b80610b3a57506001600160e01b031982166378d77ecb60e01b145b80610b5557506001600160e01b031982166301ffc9a760e01b145b92915050565b335f90815260208190526040902054600114610bb45760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b60448201526064015b60405180910390fd5b60408051838152602081018390525f916001600160a01b038616917f4dd5187225a2ae5f5ea35ca7b1732180f848cc4b6f7dce34b4c5e9f384d77dec91015b60405180910390a3505050565b6001546040516350603df360e01b8152306004820152602481018390525f916001600160a01b0316906350603df3906044015b602060405180830381865afa158015610c4e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b559190613120565b6001600160a01b0382163303610cdb5760405162461bcd60e51b815260206004820152602860248201527f455243373534305661756c742f63616e6e6f742d7365742d73656c662d61732d60448201526737b832b930ba37b960c11b6064820152608401610bab565b60405163854b89d560e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063854b89d590602401602060405180830381865afa158015610d3d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d619190613137565b610dad5760405162461bcd60e51b815260206004820152601960248201527f455243373534305661756c742f6e6f742d656e646f72736564000000000000006044820152606401610bab565b6001600160a01b0382165f8181526003602090815260408083203380855290835292819020805460ff191686151590811790915590519081529192917fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa26791015b60405180910390a35050565b6001546040516306ff657760e31b81523060048201526001600160a01b0383811660248301525f9216906337fb2bb8906044015b602060405180830381865afa158015610e68573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8c9190613120565b9392505050565b610e9c8161297a565b600154604051638b44deb160e01b81523060048201526001600160a01b03838116602483015233604483015290911690638b44deb1906064015f604051808303815f87803b158015610eec575f80fd5b505af1158015610efe573d5f803e3d5ffd5b50506040513381525f92506001600160a01b03841691507fa16c0f2cab616ed5d17cd544655b00d7062a1df7c457960cc8b9bf60770f923690602001610e0d565b335f90815260208190526040902054600114610f935760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b60408051338152602081018390525f916001600160a01b0380861692908716917f1fdc681a13d8c5da54e301c7ce6542dcde4581e4725043fdab2db12ddc574506910160405180910390a4505050565b5f610fed8261297a565b60015460405163c6f1649f60e01b8152306004820152602481018690526001600160a01b03858116604483015284811660648301529091169063c6f1649f906084016020604051808303815f875af115801561104b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061106f9190613120565b9050826001600160a01b0316826001600160a01b03167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d786846040516110bf929190918252602082015260400190565b60405180910390a39392505050565b5f7f0000000000000000000000000000000000000000000000000000000000000000461461119a5750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b507f000000000000000000000000000000000000000000000000000000000000000090565b600154604051630760168760e41b81523060048201526001600160a01b0383811660248301525f921690637601687090604401610c33565b335f9081526020819052604090205460011461124b5760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b5f826001600160a01b03167fe60d0cd4e01ab7d1e0cf1917bddb6779ca8db0fb23138e3b7a4bab6a727b966183604051610e0d91815260200190565b6001546040516308332b4560e11b81523060048201525f916001600160a01b031690631066568a90602401602060405180830381865afa1580156112cd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a639190613152565b5f6001600160a01b038316330361135b5760405162461bcd60e51b815260206004820152602860248201527f455243373534305661756c742f63616e6e6f742d7365742d73656c662d61732d60448201526737b832b930ba37b960c11b6064820152608401610bab565b335f8181526003602090815260408083206001600160a01b03881680855290835292819020805460ff191687151590811790915590519081529192917fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a350600192915050565b335f9081526020819052604090205460011461141f5760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b61142a838383612a02565b505050565b335f908152602081905260409020546001146114835760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b5f6114d18261297a565b6001546040516339517e6560e11b81523060048201526001600160a01b0385811660248301528481166044830152909116906372a2fcca906064016020604051808303815f875af1158015611528573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061154c9190613120565b60408051338152602081018390529192505f916001600160a01b0380871692908616917f295a9a8b44c0ac92394b0da92ef469784ff064156f08dab8316760c064c6cd2f91016109d0565b5f610e8c838333610fe3565b5f856001600160a01b0316876001600160a01b0316036116165760405162461bcd60e51b815260206004820152602860248201527f455243373534305661756c742f63616e6e6f742d7365742d73656c662d61732d60448201526737b832b930ba37b960c11b6064820152608401610bab565b824211156116665760405162461bcd60e51b815260206004820152601460248201527f455243373534305661756c742f657870697265640000000000000000000000006044820152606401610bab565b6001600160a01b0387165f90815260026020908152604080832087845290915290205460ff16156116d95760405162461bcd60e51b815260206004820152601f60248201527f455243373534305661756c742f617574686f72697a6174696f6e2d75736564006044820152606401610bab565b6001600160a01b0387165f9081526002602090815260408083208784529091528120805460ff1916600117905561170e6110ce565b604080517fa3efcf8cb518126a85cdfd1c1102ee539e0700189f80926e1ac37144450473fa60208201526001600160a01b03808c16928201929092529089166060820152871515608082015260a0810187905260c0810186905260e001604051602081830303815290604052805190602001206040516020016117a892919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090506117cb888285612b22565b6118225760405162461bcd60e51b815260206004820152602260248201527f455243373534305661756c742f696e76616c69642d617574686f72697a61746960448201526137b760f11b6064820152608401610bab565b6001600160a01b038881165f818152600360209081526040808320948c1680845294825291829020805460ff19168b151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3506001979650505050505050565b604051630fa1e71360e41b81525f600482018190526001600160a01b0383811660248401526044830182905290917f00000000000000000000000000000000000000000000000000000000000000009091169063fa1e713090606401602060405180830381865afa15801561190e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b559190613137565b60015460405163010476c960e71b81523060048201526001600160a01b0383811660248301525f92169063823b6480906044015b602060405180830381865afa158015611981573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8c9190613137565b6040516370a0823160e01b81526001600160a01b0382811660048301525f9185917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015611a0d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a319190613120565b1015611a895760405162461bcd60e51b815260206004820152602160248201527f455243373534305661756c742f696e73756666696369656e742d62616c616e636044820152606560f81b6064820152608401610bab565b6001600160a01b0382165f90815260036020908152604080832033845290915281205460ff16611ab95733611abb565b825b6001546040516321d26ff560e21b8152306004820152602481018890526001600160a01b03878116604483015286811660648301528084166084830152929350911690638749bfd49060a4016020604051808303815f875af1158015611b23573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b479190613137565b611b9e5760405162461bcd60e51b815260206004820152602260248201527f455243373534305661756c742f726571756573742d72656465656d2d6661696c604482015261195960f21b6064820152608401610bab565b6001546040805163e2fdcc1760e01b815290515f926001600160a01b03169163e2fdcc179160048083019260209291908290030181865afa158015611be5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c099190613179565b60405163887ca24960e01b81526001600160a01b03848116600483015286811660248301528083166044830152606482018990529192507f00000000000000000000000000000000000000000000000000000000000000009091169063887ca249906084016020604051808303815f875af1925050508015611ca8575060408051601f3d908101601f19168201909252611ca591810190613137565b60015b611d9f576040516323b872dd60e01b81526001600160a01b0385811660048301528281166024830152604482018890527f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906064016020604051808303815f875af1158015611d20573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d449190613137565b611d9a5760405162461bcd60e51b815260206004820152602160248201527f455243373534305661756c742f7472616e736665722d66726f6d2d6661696c656044820152601960fa1b6064820152608401610bab565b611da1565b505b60408051338152602081018890525f916001600160a01b0380881692908916917f1fdc681a13d8c5da54e301c7ce6542dcde4581e4725043fdab2db12ddc574506910160405180910390a4505f95945050505050565b335f90815260208190526040902054600114611e4b5760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b5f826001600160a01b03167f0ede66e1b0b7bef549c7d3a5c885444b371535620c089dc7b92ddf8550edaa1983604051610e0d91815260200190565b5f6001600160a01b038216331480611ec157506001600160a01b0382165f90815260036020908152604080832033845290915290205460ff165b611f0d5760405162461bcd60e51b815260206004820152601a60248201527f455243373534305661756c742f696e76616c69642d6f776e65720000000000006044820152606401610bab565b6040516370a0823160e01b81526001600160a01b03838116600483015285917f0000000000000000000000000000000000000000000000000000000000000000909116906370a0823190602401602060405180830381865afa158015611f75573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f999190613120565b1015611ff15760405162461bcd60e51b815260206004820152602160248201527f455243373534305661756c742f696e73756666696369656e742d62616c616e636044820152606560f81b6064820152608401610bab565b600154604051620bcc0d60e41b8152306004820152602481018690526001600160a01b03858116604483015284811660648301523360848301529091169062bcc0d09060a4016020604051808303815f875af1158015612053573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120779190613137565b6120cf5760405162461bcd60e51b815260206004820152602360248201527f455243373534305661756c742f726571756573742d6465706f7369742d6661696044820152621b195960ea1b6064820152608401610bab565b61216e7f00000000000000000000000000000000000000000000000000000000000000008360015f9054906101000a90046001600160a01b03166001600160a01b031663e2fdcc176040518163ffffffff1660e01b8152600401602060405180830381865afa158015612144573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121689190613179565b87612d00565b60408051338152602081018690525f916001600160a01b0380861692908716917fbb58420bb8ce44e11b84e214cc0de10ce5e7c24d0355b2815c3d758b514cae72910160405180910390a4505f9392505050565b5f610e8c838333612824565b5f610a6361040a7f0000000000000000000000000000000000000000000000000000000000000000600a61328b565b5f610e8c826111bf565b335f9081526020819052604090205460011461225b5760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b335f908152602081905260409020546001146122f25760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b60408051838152602081018390525f916001600160a01b038616917fad23d6d908f14df9b90c8c580954f8a95c4a6e3261e49af08db21e6aaadcd1289101610bf3565b600154604051631495d74f60e01b81523060048201526001600160a01b0383811660248301525f921690631495d74f90604401610e4d565b6001546040516308a44dc760e21b81523060048201526001600160a01b0383811660248301525f921690632291371c90604401610e4d565b5f6123af8261297a565b600154604051636fe6a09760e11b8152306004820152602481018690526001600160a01b03858116604483015284811660648301529091169063dfcd412e906084016020604051808303815f875af115801561240d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124319190613120565b9050816001600160a01b0316836001600160a01b0316336001600160a01b03167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db87856040516109d0929190918252602082015260400190565b6124948161297a565b60015460405163230096f760e21b81523060048201526001600160a01b03838116602483015233604483015290911690638c025bdc906064015f604051808303815f87803b1580156124e4575f80fd5b505af11580156124f6573d5f803e3d5ffd5b50506040513381525f92506001600160a01b03841691507f4ae0134aad5d0e98e82f45680facd628ee6b5aa85ad9a85248a7ef47319f8c5090602001610e0d565b5f6125418261297a565b60015460405163fea53be160e01b8152306004820152602481018690526001600160a01b03858116604483015284811660648301529091169063fea53be1906084016020604051808303815f875af115801561259f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125c39190613120565b9050816001600160a01b0316836001600160a01b0316336001600160a01b03167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db84886040516109d0929190918252602082015260400190565b60015460405163f2e586db60e01b81523060048201526001600160a01b0383811660248301525f92169063f2e586db90604401610c33565b600154604051633e5541f160e01b8152306004820152602481018390525f916001600160a01b031690633e5541f190604401610c33565b6001546040516308c22e9b60e41b81523060048201526001600160a01b0383811660248301525f921690638c22e9b090604401610c33565b335f908152602081905260409020546001146127185760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b816636b0b730b3b2b960c91b03612756576001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556127aa565b60405162461bcd60e51b8152602060048201526024808201527f455243373534305661756c742f66696c652d756e7265636f676e697a65642d706044820152636172616d60e01b6064820152608401610bab565b6040516001600160a01b038216815282907f8fef588b5fc1afbf5b2f06c1a435d513f208da2e6704c3d8f0e0ec91167066ba9060200160405180910390a25050565b6001546040516395b734fb60e01b81523060048201526001600160a01b0383811660248301525f9216906395b734fb90604401610c33565b5f61282e8261297a565b600154604051633a4d2cd160e01b8152306004820152602481018690526001600160a01b038581166044830152848116606483015290911690633a4d2cd1906084016020604051808303815f875af115801561288c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128b09190613120565b9050826001600160a01b0316826001600160a01b03167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d783876040516110bf929190918252602082015260400190565b5f610e8c826127ec565b600154604051631b5fa0df60e21b81523060048201526001600160a01b0383811660248301525f921690636d7e837c90604401611966565b600154604051638ae5ecff60e01b81523060048201526001600160a01b0383811660248301525f921690638ae5ecff90604401610e4d565b6001600160a01b0381163314806129b357506001600160a01b0381165f90815260036020908152604080832033845290915290205460ff165b6129ff5760405162461bcd60e51b815260206004820152601f60248201527f455243373534305661756c742f696e76616c69642d636f6e74726f6c6c6572006044820152606401610bab565b50565b6040516001600160a01b038381166024830152604482018390525f91829186169060640160408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251612a5b9190613299565b5f604051808303815f865af19150503d805f8114612a94576040519150601f19603f3d011682016040523d82523d5f602084013e612a99565b606091505b5091509150818015612ac3575080511580612ac3575080806020019051810190612ac39190613137565b612b1b5760405162461bcd60e51b8152602060048201526024808201527f536166655472616e736665724c69622f736166652d7472616e736665722d66616044820152631a5b195960e21b6064820152608401610bab565b5050505050565b5f6001600160a01b038416612b795760405162461bcd60e51b815260206004820152601b60248201527f5369676e61747572654c69622f696e76616c69642d7369676e657200000000006044820152606401610bab565b8151604103612c115760208281015160408085015160608087015183515f8082529681018086528a9052951a928501839052840183905260808401819052919260019060a0016020604051602081039080840390855afa158015612bdf573d5f803e3d5ffd5b505050602060405103516001600160a01b0316876001600160a01b031603612c0d5760019350505050610e8c565b5050505b6001600160a01b0384163b15610e8c575f80856001600160a01b03168585604051602401612c409291906132af565b60408051601f198184030181529181526020820180516001600160e01b0316630b135d3f60e11b17905251612c759190613299565b5f60405180830381855afa9150503d805f8114612cad576040519150601f19603f3d011682016040523d82523d5f602084013e612cb2565b606091505b5091509150818015612cc5575080516020145b8015612cf657508051630b135d3f60e11b90612cea90830160209081019084016132eb565b6001600160e01b031916145b9695505050505050565b6040516001600160a01b0384811660248301528381166044830152606482018390525f91829187169060840160408051601f198184030181529181526020820180516001600160e01b03166323b872dd60e01b17905251612d619190613299565b5f604051808303815f865af19150503d805f8114612d9a576040519150601f19603f3d011682016040523d82523d5f602084013e612d9f565b606091505b5091509150818015612dc9575080511580612dc9575080806020019051810190612dc99190613137565b612e275760405162461bcd60e51b815260206004820152602960248201527f536166655472616e736665724c69622f736166652d7472616e736665722d66726044820152681bdb4b59985a5b195960ba1b6064820152608401610bab565b505050505050565b6001600160a01b03811681146129ff575f80fd5b5f805f60608486031215612e55575f80fd5b833592506020840135612e6781612e2f565b91506040840135612e7781612e2f565b809150509250925092565b6001600160e01b0319811681146129ff575f80fd5b5f60208284031215612ea7575f80fd5b8135610e8c81612e82565b5f805f60608486031215612ec4575f80fd5b8335612ecf81612e2f565b95602085013595506040909401359392505050565b5f60208284031215612ef4575f80fd5b5035919050565b80151581146129ff575f80fd5b5f8060408385031215612f19575f80fd5b8235612f2481612e2f565b91506020830135612f3481612efb565b809150509250929050565b5f8060408385031215612f50575f80fd5b823591506020830135612f3481612e2f565b5f805f60608486031215612f74575f80fd5b8335612f7f81612e2f565b92506020840135612f8f81612e2f565b929592945050506040919091013590565b5f60208284031215612fb0575f80fd5b8135610e8c81612e2f565b5f8060408385031215612fcc575f80fd5b8235612fd781612e2f565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b5f805f805f8060c0878903121561300e575f80fd5b863561301981612e2f565b9550602087013561302981612e2f565b9450604087013561303981612efb565b9350606087013592506080870135915060a087013567ffffffffffffffff811115613062575f80fd5b8701601f81018913613072575f80fd5b803567ffffffffffffffff81111561308c5761308c612fe5565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156130bb576130bb612fe5565b6040528181528282016020018b10156130d2575f80fd5b816020840160208301375f602083830101528093505050509295509295509295565b5f8060408385031215613105575f80fd5b823561311081612e2f565b91506020830135612f3481612e2f565b5f60208284031215613130575f80fd5b5051919050565b5f60208284031215613147575f80fd5b8151610e8c81612efb565b5f60208284031215613162575f80fd5b815167ffffffffffffffff81168114610e8c575f80fd5b5f60208284031215613189575f80fd5b8151610e8c81612e2f565b634e487b7160e01b5f52601160045260245ffd5b6001815b60018411156131e3578085048111156131c7576131c7613194565b60018416156131d557908102905b60019390931c9280026131ac565b935093915050565b5f826131f957506001610b55565b8161320557505f610b55565b816001811461321b576002811461322557613241565b6001915050610b55565b60ff84111561323657613236613194565b50506001821b610b55565b5060208310610133831016604e8410600b8410161715613264575081810a610b55565b6132705f1984846131a8565b805f190482111561328357613283613194565b029392505050565b5f610e8c60ff8416836131eb565b5f82518060208501845e5f920191825250919050565b828152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b5f602082840312156132fb575f80fd5b8151610e8c81612e8256fea264697066735822122094b32c2278c06e76b79743bf72bbcf94ae2e0f02ebabf5b53e5acd23229e7edf64736f6c634300081a003300000000000000000000000000000000000000000000000000000000f6bd674f97aa65f23e7be09fcd62d0554d2e927300000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000008c213ee79581ff4984583c6a801e5263418c4b860000000000000000000000000c1fdfd6a1331a875ea013f3897fc8a76ada5dfc000000000000000000000000427a1ce127b1775e4cbd4f58ad468b9f832ea7e9
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610392575f3560e01c806384ce2bf7116101df578063ba08765211610109578063d4e8be83116100a9578063ebf0c71711610079578063ebf0c717146108b7578063ef8b30f71461040f578063f15b65b1146108de578063f5a23d8d146108f1575f80fd5b8063d4e8be831461086b578063d905777e1461087e578063da39b3e714610891578063eaed1d07146108a4575f80fd5b8063c6e6f592116100e4578063c6e6f592146107f1578063cd0d009614610804578063cdf5bba31461082b578063ce96cb7714610858575f80fd5b8063ba087652146107ac578063bf353dbb146107bf578063c63d75b6146107de575f80fd5b8063a8d5fd651161017f578063b460af941161014f578063b460af9414610710578063b6363cf214610723578063b7adb4c514610750578063b9cf063414610799575f80fd5b8063a8d5fd65146106c3578063aabb5922146106ea578063b04a5e05146106fd578063b3d7f6b91461040f575f80fd5b806399530b06116101ba57806399530b0614610682578063995ea21a1461068a5780639c52a7f11461069d578063a21ec79f146106b0575f80fd5b806384ce2bf71461064957806385b77f451461065c57806394bf804d1461066f575f80fd5b80633e0dc34e116102c05780635f3e849f11610260578063711b58ff11610230578063711b58ff146105fd57806378d77ecb146106105780637c1b50c4146106235780637d41c86e14610636575f80fd5b80635f3e849f146105b157806365fae35e146105c457806369d77a44146105d75780636e553f65146105ea575f80fd5b80634b5fd6661161029b5780634b5fd666146105835780634cdad5061461040f57806352aaead814610596578063558a72971461059e575f80fd5b80633e0dc34e1461051d578063402d267d1461055d578063481c6a7514610570575f80fd5b806321f075ee116103365780632cdfbae5116103065780632cdfbae5146104b05780632e2d2984146104c35780633644e515146104d657806338d52e0f146104de575f80fd5b806321f075ee14610444578063234f0e3b1461045757806326c6f96c1461048a5780632b9d9c1f1461049d575f80fd5b80630263704b116103715780630263704b146103e757806307a2d13a146103fc5780630a28a4771461040f5780630d62c3321461041d575f80fd5b8062a06d191461039657806301e1d114146103bc57806301ffc9a7146103c4575b5f80fd5b6103a96103a4366004612e43565b610904565b6040519081526020015b60405180910390f35b6103a96109df565b6103d76103d2366004612e97565b610a68565b60405190151581526020016103b3565b6103fa6103f5366004612eb2565b610b5b565b005b6103a961040a366004612ee4565b610c00565b6103a9610392366004612ee4565b6103a97fa3efcf8cb518126a85cdfd1c1102ee539e0700189f80926e1ac37144450473fa81565b6103fa610452366004612f08565b610c72565b6103fa610465366004612ee4565b335f90815260026020908152604080832093835292905220805460ff19166001179055565b6103a9610498366004612f3f565b610e19565b6103fa6104ab366004612f3f565b610e93565b6103fa6104be366004612f62565b610f3f565b6103a96104d1366004612e43565b610fe3565b6103a96110ce565b6105057f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b6040516001600160a01b0390911681526020016103b3565b6105447f00000000000000000000000000000000000000000000000000000000f6bd674f81565b60405167ffffffffffffffff90911681526020016103b3565b6103a961056b366004612fa0565b6111bf565b600154610505906001600160a01b031681565b6103fa610591366004612fbb565b6111f7565b610544611287565b6103d76105ac366004612f08565b6112f1565b6103fa6105bf366004612f62565b6113cb565b6103fa6105d2366004612fa0565b61142f565b6103a96105e5366004612e43565b6114c7565b6103a96105f8366004612f3f565b611597565b6103d761060b366004612ff9565b6115a3565b6103d761061e366004612fa0565b611897565b6103d7610631366004612f3f565b611932565b6103a9610644366004612e43565b6119a5565b6103fa610657366004612fbb565b611df7565b6103a961066a366004612e43565b611e87565b6103a961067d366004612f3f565b6121c2565b6103a96121ce565b6103a9610698366004612f3f565b6121fd565b6103fa6106ab366004612fa0565b612207565b6103fa6106be366004612eb2565b61229e565b6105057f0000000000000000000000008c213ee79581ff4984583c6a801e5263418c4b8681565b6103a96106f8366004612f3f565b612335565b6103a961070b366004612f3f565b61236d565b6103a961071e366004612e43565b6123a5565b6103d76107313660046130f4565b600360209081525f928352604080842090915290825290205460ff1681565b6107777f97aa65f23e7be09fcd62d0554d2e92730000000000000000000000000000000081565b6040516fffffffffffffffffffffffffffffffff1990911681526020016103b3565b6103fa6107a7366004612f3f565b61248b565b6103a96107ba366004612e43565b612537565b6103a96107cd366004612fa0565b5f6020819052908152604090205481565b6103a96107ec366004612fa0565b61261d565b6103a96107ff366004612ee4565b612655565b6103a97f000000000000000000000000000000000000000000000000000000000000000181565b6103d7610839366004612fbb565b600260209081525f928352604080842090915290825290205460ff1681565b6103a9610866366004612fa0565b61268c565b6103fa610879366004612f3f565b6126c4565b6103a961088c366004612fa0565b6127ec565b6103a961089f366004612e43565b612824565b6103a96108b2366004612f3f565b612900565b6105057f0000000000000000000000000c1fdfd6a1331a875ea013f3897fc8a76ada5dfc81565b6103d76108ec366004612f3f565b61290a565b6103a96108ff366004612f3f565b612942565b5f61090e8261297a565b6001546040516311dcd79160e01b81523060048201526001600160a01b0385811660248301528481166044830152909116906311dcd791906064016020604051808303815f875af1158015610965573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109899190613120565b60408051338152602081018390529192505f916001600160a01b0380871692908616917f9c133d4657dc9cd12f4c08cef86ef778dbbe03f3ad3b661ff14d36bc3febb1fb91015b60405180910390a49392505050565b5f610a637f0000000000000000000000008c213ee79581ff4984583c6a801e5263418c4b866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a3f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061040a9190613120565b905090565b5f6001600160e01b03198216630ce3bbe560e41b1480610a9857506001600160e01b03198216631883ba3960e21b145b80610ab357506001600160e01b0319821663e3bc4e6560e01b145b80610ace57506001600160e01b03198216638bf840e360e01b145b80610ae957506001600160e01b0319821663e76cffc760e01b145b80610b0457506001600160e01b03198216632f0a18c560e01b145b80610b1f57506001600160e01b031982166354f2843960e11b145b80610b3a57506001600160e01b031982166378d77ecb60e01b145b80610b5557506001600160e01b031982166301ffc9a760e01b145b92915050565b335f90815260208190526040902054600114610bb45760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b60448201526064015b60405180910390fd5b60408051838152602081018390525f916001600160a01b038616917f4dd5187225a2ae5f5ea35ca7b1732180f848cc4b6f7dce34b4c5e9f384d77dec91015b60405180910390a3505050565b6001546040516350603df360e01b8152306004820152602481018390525f916001600160a01b0316906350603df3906044015b602060405180830381865afa158015610c4e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b559190613120565b6001600160a01b0382163303610cdb5760405162461bcd60e51b815260206004820152602860248201527f455243373534305661756c742f63616e6e6f742d7365742d73656c662d61732d60448201526737b832b930ba37b960c11b6064820152608401610bab565b60405163854b89d560e01b81523360048201527f0000000000000000000000000c1fdfd6a1331a875ea013f3897fc8a76ada5dfc6001600160a01b03169063854b89d590602401602060405180830381865afa158015610d3d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d619190613137565b610dad5760405162461bcd60e51b815260206004820152601960248201527f455243373534305661756c742f6e6f742d656e646f72736564000000000000006044820152606401610bab565b6001600160a01b0382165f8181526003602090815260408083203380855290835292819020805460ff191686151590811790915590519081529192917fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa26791015b60405180910390a35050565b6001546040516306ff657760e31b81523060048201526001600160a01b0383811660248301525f9216906337fb2bb8906044015b602060405180830381865afa158015610e68573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8c9190613120565b9392505050565b610e9c8161297a565b600154604051638b44deb160e01b81523060048201526001600160a01b03838116602483015233604483015290911690638b44deb1906064015f604051808303815f87803b158015610eec575f80fd5b505af1158015610efe573d5f803e3d5ffd5b50506040513381525f92506001600160a01b03841691507fa16c0f2cab616ed5d17cd544655b00d7062a1df7c457960cc8b9bf60770f923690602001610e0d565b335f90815260208190526040902054600114610f935760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b60408051338152602081018390525f916001600160a01b0380861692908716917f1fdc681a13d8c5da54e301c7ce6542dcde4581e4725043fdab2db12ddc574506910160405180910390a4505050565b5f610fed8261297a565b60015460405163c6f1649f60e01b8152306004820152602481018690526001600160a01b03858116604483015284811660648301529091169063c6f1649f906084016020604051808303815f875af115801561104b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061106f9190613120565b9050826001600160a01b0316826001600160a01b03167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d786846040516110bf929190918252602082015260400190565b60405180910390a39392505050565b5f7f0000000000000000000000000000000000000000000000000000000000000001461461119a5750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527fe416b338a274162320c79445ae6604141d1cb08275eb27011b69f002dc094d05828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b507fab230659ac4ef2f939259733effe6aa258c2fe5644434ea2de6831ec985ba7dd90565b600154604051630760168760e41b81523060048201526001600160a01b0383811660248301525f921690637601687090604401610c33565b335f9081526020819052604090205460011461124b5760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b5f826001600160a01b03167fe60d0cd4e01ab7d1e0cf1917bddb6779ca8db0fb23138e3b7a4bab6a727b966183604051610e0d91815260200190565b6001546040516308332b4560e11b81523060048201525f916001600160a01b031690631066568a90602401602060405180830381865afa1580156112cd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a639190613152565b5f6001600160a01b038316330361135b5760405162461bcd60e51b815260206004820152602860248201527f455243373534305661756c742f63616e6e6f742d7365742d73656c662d61732d60448201526737b832b930ba37b960c11b6064820152608401610bab565b335f8181526003602090815260408083206001600160a01b03881680855290835292819020805460ff191687151590811790915590519081529192917fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a350600192915050565b335f9081526020819052604090205460011461141f5760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b61142a838383612a02565b505050565b335f908152602081905260409020546001146114835760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b5f6114d18261297a565b6001546040516339517e6560e11b81523060048201526001600160a01b0385811660248301528481166044830152909116906372a2fcca906064016020604051808303815f875af1158015611528573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061154c9190613120565b60408051338152602081018390529192505f916001600160a01b0380871692908616917f295a9a8b44c0ac92394b0da92ef469784ff064156f08dab8316760c064c6cd2f91016109d0565b5f610e8c838333610fe3565b5f856001600160a01b0316876001600160a01b0316036116165760405162461bcd60e51b815260206004820152602860248201527f455243373534305661756c742f63616e6e6f742d7365742d73656c662d61732d60448201526737b832b930ba37b960c11b6064820152608401610bab565b824211156116665760405162461bcd60e51b815260206004820152601460248201527f455243373534305661756c742f657870697265640000000000000000000000006044820152606401610bab565b6001600160a01b0387165f90815260026020908152604080832087845290915290205460ff16156116d95760405162461bcd60e51b815260206004820152601f60248201527f455243373534305661756c742f617574686f72697a6174696f6e2d75736564006044820152606401610bab565b6001600160a01b0387165f9081526002602090815260408083208784529091528120805460ff1916600117905561170e6110ce565b604080517fa3efcf8cb518126a85cdfd1c1102ee539e0700189f80926e1ac37144450473fa60208201526001600160a01b03808c16928201929092529089166060820152871515608082015260a0810187905260c0810186905260e001604051602081830303815290604052805190602001206040516020016117a892919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090506117cb888285612b22565b6118225760405162461bcd60e51b815260206004820152602260248201527f455243373534305661756c742f696e76616c69642d617574686f72697a61746960448201526137b760f11b6064820152608401610bab565b6001600160a01b038881165f818152600360209081526040808320948c1680845294825291829020805460ff19168b151590811790915591519182527fceb576d9f15e4e200fdb5096d64d5dfd667e16def20c1eefd14256d8e3faa267910160405180910390a3506001979650505050505050565b604051630fa1e71360e41b81525f600482018190526001600160a01b0383811660248401526044830182905290917f0000000000000000000000008c213ee79581ff4984583c6a801e5263418c4b869091169063fa1e713090606401602060405180830381865afa15801561190e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b559190613137565b60015460405163010476c960e71b81523060048201526001600160a01b0383811660248301525f92169063823b6480906044015b602060405180830381865afa158015611981573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8c9190613137565b6040516370a0823160e01b81526001600160a01b0382811660048301525f9185917f0000000000000000000000008c213ee79581ff4984583c6a801e5263418c4b8616906370a0823190602401602060405180830381865afa158015611a0d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a319190613120565b1015611a895760405162461bcd60e51b815260206004820152602160248201527f455243373534305661756c742f696e73756666696369656e742d62616c616e636044820152606560f81b6064820152608401610bab565b6001600160a01b0382165f90815260036020908152604080832033845290915281205460ff16611ab95733611abb565b825b6001546040516321d26ff560e21b8152306004820152602481018890526001600160a01b03878116604483015286811660648301528084166084830152929350911690638749bfd49060a4016020604051808303815f875af1158015611b23573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b479190613137565b611b9e5760405162461bcd60e51b815260206004820152602260248201527f455243373534305661756c742f726571756573742d72656465656d2d6661696c604482015261195960f21b6064820152608401610bab565b6001546040805163e2fdcc1760e01b815290515f926001600160a01b03169163e2fdcc179160048083019260209291908290030181865afa158015611be5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c099190613179565b60405163887ca24960e01b81526001600160a01b03848116600483015286811660248301528083166044830152606482018990529192507f0000000000000000000000008c213ee79581ff4984583c6a801e5263418c4b869091169063887ca249906084016020604051808303815f875af1925050508015611ca8575060408051601f3d908101601f19168201909252611ca591810190613137565b60015b611d9f576040516323b872dd60e01b81526001600160a01b0385811660048301528281166024830152604482018890527f0000000000000000000000008c213ee79581ff4984583c6a801e5263418c4b8616906323b872dd906064016020604051808303815f875af1158015611d20573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d449190613137565b611d9a5760405162461bcd60e51b815260206004820152602160248201527f455243373534305661756c742f7472616e736665722d66726f6d2d6661696c656044820152601960fa1b6064820152608401610bab565b611da1565b505b60408051338152602081018890525f916001600160a01b0380881692908916917f1fdc681a13d8c5da54e301c7ce6542dcde4581e4725043fdab2db12ddc574506910160405180910390a4505f95945050505050565b335f90815260208190526040902054600114611e4b5760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b5f826001600160a01b03167f0ede66e1b0b7bef549c7d3a5c885444b371535620c089dc7b92ddf8550edaa1983604051610e0d91815260200190565b5f6001600160a01b038216331480611ec157506001600160a01b0382165f90815260036020908152604080832033845290915290205460ff165b611f0d5760405162461bcd60e51b815260206004820152601a60248201527f455243373534305661756c742f696e76616c69642d6f776e65720000000000006044820152606401610bab565b6040516370a0823160e01b81526001600160a01b03838116600483015285917f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48909116906370a0823190602401602060405180830381865afa158015611f75573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f999190613120565b1015611ff15760405162461bcd60e51b815260206004820152602160248201527f455243373534305661756c742f696e73756666696369656e742d62616c616e636044820152606560f81b6064820152608401610bab565b600154604051620bcc0d60e41b8152306004820152602481018690526001600160a01b03858116604483015284811660648301523360848301529091169062bcc0d09060a4016020604051808303815f875af1158015612053573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120779190613137565b6120cf5760405162461bcd60e51b815260206004820152602360248201527f455243373534305661756c742f726571756573742d6465706f7369742d6661696044820152621b195960ea1b6064820152608401610bab565b61216e7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488360015f9054906101000a90046001600160a01b03166001600160a01b031663e2fdcc176040518163ffffffff1660e01b8152600401602060405180830381865afa158015612144573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121689190613179565b87612d00565b60408051338152602081018690525f916001600160a01b0380861692908716917fbb58420bb8ce44e11b84e214cc0de10ce5e7c24d0355b2815c3d758b514cae72910160405180910390a4505f9392505050565b5f610e8c838333612824565b5f610a6361040a7f0000000000000000000000000000000000000000000000000000000000000006600a61328b565b5f610e8c826111bf565b335f9081526020819052604090205460011461225b5760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b335f908152602081905260409020546001146122f25760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b60408051838152602081018390525f916001600160a01b038616917fad23d6d908f14df9b90c8c580954f8a95c4a6e3261e49af08db21e6aaadcd1289101610bf3565b600154604051631495d74f60e01b81523060048201526001600160a01b0383811660248301525f921690631495d74f90604401610e4d565b6001546040516308a44dc760e21b81523060048201526001600160a01b0383811660248301525f921690632291371c90604401610e4d565b5f6123af8261297a565b600154604051636fe6a09760e11b8152306004820152602481018690526001600160a01b03858116604483015284811660648301529091169063dfcd412e906084016020604051808303815f875af115801561240d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124319190613120565b9050816001600160a01b0316836001600160a01b0316336001600160a01b03167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db87856040516109d0929190918252602082015260400190565b6124948161297a565b60015460405163230096f760e21b81523060048201526001600160a01b03838116602483015233604483015290911690638c025bdc906064015f604051808303815f87803b1580156124e4575f80fd5b505af11580156124f6573d5f803e3d5ffd5b50506040513381525f92506001600160a01b03841691507f4ae0134aad5d0e98e82f45680facd628ee6b5aa85ad9a85248a7ef47319f8c5090602001610e0d565b5f6125418261297a565b60015460405163fea53be160e01b8152306004820152602481018690526001600160a01b03858116604483015284811660648301529091169063fea53be1906084016020604051808303815f875af115801561259f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125c39190613120565b9050816001600160a01b0316836001600160a01b0316336001600160a01b03167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db84886040516109d0929190918252602082015260400190565b60015460405163f2e586db60e01b81523060048201526001600160a01b0383811660248301525f92169063f2e586db90604401610c33565b600154604051633e5541f160e01b8152306004820152602481018390525f916001600160a01b031690633e5541f190604401610c33565b6001546040516308c22e9b60e41b81523060048201526001600160a01b0383811660248301525f921690638c22e9b090604401610c33565b335f908152602081905260409020546001146127185760405162461bcd60e51b8152602060048201526013602482015272105d5d1a0bdb9bdd0b585d5d1a1bdc9a5e9959606a1b6044820152606401610bab565b816636b0b730b3b2b960c91b03612756576001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556127aa565b60405162461bcd60e51b8152602060048201526024808201527f455243373534305661756c742f66696c652d756e7265636f676e697a65642d706044820152636172616d60e01b6064820152608401610bab565b6040516001600160a01b038216815282907f8fef588b5fc1afbf5b2f06c1a435d513f208da2e6704c3d8f0e0ec91167066ba9060200160405180910390a25050565b6001546040516395b734fb60e01b81523060048201526001600160a01b0383811660248301525f9216906395b734fb90604401610c33565b5f61282e8261297a565b600154604051633a4d2cd160e01b8152306004820152602481018690526001600160a01b038581166044830152848116606483015290911690633a4d2cd1906084016020604051808303815f875af115801561288c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128b09190613120565b9050826001600160a01b0316826001600160a01b03167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d783876040516110bf929190918252602082015260400190565b5f610e8c826127ec565b600154604051631b5fa0df60e21b81523060048201526001600160a01b0383811660248301525f921690636d7e837c90604401611966565b600154604051638ae5ecff60e01b81523060048201526001600160a01b0383811660248301525f921690638ae5ecff90604401610e4d565b6001600160a01b0381163314806129b357506001600160a01b0381165f90815260036020908152604080832033845290915290205460ff165b6129ff5760405162461bcd60e51b815260206004820152601f60248201527f455243373534305661756c742f696e76616c69642d636f6e74726f6c6c6572006044820152606401610bab565b50565b6040516001600160a01b038381166024830152604482018390525f91829186169060640160408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251612a5b9190613299565b5f604051808303815f865af19150503d805f8114612a94576040519150601f19603f3d011682016040523d82523d5f602084013e612a99565b606091505b5091509150818015612ac3575080511580612ac3575080806020019051810190612ac39190613137565b612b1b5760405162461bcd60e51b8152602060048201526024808201527f536166655472616e736665724c69622f736166652d7472616e736665722d66616044820152631a5b195960e21b6064820152608401610bab565b5050505050565b5f6001600160a01b038416612b795760405162461bcd60e51b815260206004820152601b60248201527f5369676e61747572654c69622f696e76616c69642d7369676e657200000000006044820152606401610bab565b8151604103612c115760208281015160408085015160608087015183515f8082529681018086528a9052951a928501839052840183905260808401819052919260019060a0016020604051602081039080840390855afa158015612bdf573d5f803e3d5ffd5b505050602060405103516001600160a01b0316876001600160a01b031603612c0d5760019350505050610e8c565b5050505b6001600160a01b0384163b15610e8c575f80856001600160a01b03168585604051602401612c409291906132af565b60408051601f198184030181529181526020820180516001600160e01b0316630b135d3f60e11b17905251612c759190613299565b5f60405180830381855afa9150503d805f8114612cad576040519150601f19603f3d011682016040523d82523d5f602084013e612cb2565b606091505b5091509150818015612cc5575080516020145b8015612cf657508051630b135d3f60e11b90612cea90830160209081019084016132eb565b6001600160e01b031916145b9695505050505050565b6040516001600160a01b0384811660248301528381166044830152606482018390525f91829187169060840160408051601f198184030181529181526020820180516001600160e01b03166323b872dd60e01b17905251612d619190613299565b5f604051808303815f865af19150503d805f8114612d9a576040519150601f19603f3d011682016040523d82523d5f602084013e612d9f565b606091505b5091509150818015612dc9575080511580612dc9575080806020019051810190612dc99190613137565b612e275760405162461bcd60e51b815260206004820152602960248201527f536166655472616e736665724c69622f736166652d7472616e736665722d66726044820152681bdb4b59985a5b195960ba1b6064820152608401610bab565b505050505050565b6001600160a01b03811681146129ff575f80fd5b5f805f60608486031215612e55575f80fd5b833592506020840135612e6781612e2f565b91506040840135612e7781612e2f565b809150509250925092565b6001600160e01b0319811681146129ff575f80fd5b5f60208284031215612ea7575f80fd5b8135610e8c81612e82565b5f805f60608486031215612ec4575f80fd5b8335612ecf81612e2f565b95602085013595506040909401359392505050565b5f60208284031215612ef4575f80fd5b5035919050565b80151581146129ff575f80fd5b5f8060408385031215612f19575f80fd5b8235612f2481612e2f565b91506020830135612f3481612efb565b809150509250929050565b5f8060408385031215612f50575f80fd5b823591506020830135612f3481612e2f565b5f805f60608486031215612f74575f80fd5b8335612f7f81612e2f565b92506020840135612f8f81612e2f565b929592945050506040919091013590565b5f60208284031215612fb0575f80fd5b8135610e8c81612e2f565b5f8060408385031215612fcc575f80fd5b8235612fd781612e2f565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b5f805f805f8060c0878903121561300e575f80fd5b863561301981612e2f565b9550602087013561302981612e2f565b9450604087013561303981612efb565b9350606087013592506080870135915060a087013567ffffffffffffffff811115613062575f80fd5b8701601f81018913613072575f80fd5b803567ffffffffffffffff81111561308c5761308c612fe5565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156130bb576130bb612fe5565b6040528181528282016020018b10156130d2575f80fd5b816020840160208301375f602083830101528093505050509295509295509295565b5f8060408385031215613105575f80fd5b823561311081612e2f565b91506020830135612f3481612e2f565b5f60208284031215613130575f80fd5b5051919050565b5f60208284031215613147575f80fd5b8151610e8c81612efb565b5f60208284031215613162575f80fd5b815167ffffffffffffffff81168114610e8c575f80fd5b5f60208284031215613189575f80fd5b8151610e8c81612e2f565b634e487b7160e01b5f52601160045260245ffd5b6001815b60018411156131e3578085048111156131c7576131c7613194565b60018416156131d557908102905b60019390931c9280026131ac565b935093915050565b5f826131f957506001610b55565b8161320557505f610b55565b816001811461321b576002811461322557613241565b6001915050610b55565b60ff84111561323657613236613194565b50506001821b610b55565b5060208310610133831016604e8410600b8410161715613264575081810a610b55565b6132705f1984846131a8565b805f190482111561328357613283613194565b029392505050565b5f610e8c60ff8416836131eb565b5f82518060208501845e5f920191825250919050565b828152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b5f602082840312156132fb575f80fd5b8151610e8c81612e8256fea264697066735822122094b32c2278c06e76b79743bf72bbcf94ae2e0f02ebabf5b53e5acd23229e7edf64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000f6bd674f97aa65f23e7be09fcd62d0554d2e927300000000000000000000000000000000000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000008c213ee79581ff4984583c6a801e5263418c4b860000000000000000000000000c1fdfd6a1331a875ea013f3897fc8a76ada5dfc000000000000000000000000427a1ce127b1775e4cbd4f58ad468b9f832ea7e9
-----Decoded View---------------
Arg [0] : poolId_ (uint64): 4139607887
Arg [1] : trancheId_ (bytes16): 0x97aa65f23e7be09fcd62d0554d2e9273
Arg [2] : asset_ (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [3] : share_ (address): 0x8c213ee79581Ff4984583C6a801e5263418C4b86
Arg [4] : root_ (address): 0x0C1fDfd6a1331a875EA013F3897fc8a76ada5DfC
Arg [5] : manager_ (address): 0x427A1ce127b1775e4Cbd4F58ad468B9F832eA7e9
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000f6bd674f
Arg [1] : 97aa65f23e7be09fcd62d0554d2e927300000000000000000000000000000000
Arg [2] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [3] : 0000000000000000000000008c213ee79581ff4984583c6a801e5263418c4b86
Arg [4] : 0000000000000000000000000c1fdfd6a1331a875ea013f3897fc8a76ada5dfc
Arg [5] : 000000000000000000000000427a1ce127b1775e4cbd4f58ad468b9f832ea7e9
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.