Latest 25 from a total of 26,725 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Deposit To App C... | 315379478 | 326 days ago | IN | 0.00020742 ETH | 0.00000022 | ||||
| Deposit To App C... | 312645563 | 334 days ago | IN | 0.00009816 ETH | 0.00000143 | ||||
| Deposit To App C... | 312637884 | 334 days ago | IN | 0.00009805 ETH | 0.00000142 | ||||
| Deposit To App C... | 312635085 | 334 days ago | IN | 0.00009798 ETH | 0.00000142 | ||||
| Deposit To App C... | 312634452 | 334 days ago | IN | 0.00009808 ETH | 0.00000142 | ||||
| Deposit To App C... | 312624234 | 334 days ago | IN | 0.000098 ETH | 0.00000142 | ||||
| Deposit To App C... | 312623590 | 334 days ago | IN | 0.00009777 ETH | 0.00000141 | ||||
| Deposit To App C... | 312579993 | 334 days ago | IN | 0.00010182 ETH | 0.00000163 | ||||
| Deposit To App C... | 311828314 | 336 days ago | IN | 0.00011477 ETH | 0.00000264 | ||||
| Deposit To App C... | 311827884 | 336 days ago | IN | 0.00011332 ETH | 0.00000255 | ||||
| Deposit To App C... | 311824055 | 336 days ago | IN | 0.00011312 ETH | 0.00000254 | ||||
| Deposit To App C... | 311823604 | 336 days ago | IN | 0.00010931 ETH | 0.00000233 | ||||
| Deposit To App C... | 311823278 | 336 days ago | IN | 0.00010931 ETH | 0.00000233 | ||||
| Deposit To App C... | 311822221 | 336 days ago | IN | 0.00010931 ETH | 0.00000233 | ||||
| Deposit To App C... | 311818824 | 336 days ago | IN | 0.00010794 ETH | 0.00000225 | ||||
| Deposit To App C... | 311812444 | 336 days ago | IN | 0.00010627 ETH | 0.00000278 | ||||
| Deposit To App C... | 311808965 | 336 days ago | IN | 0.00011397 ETH | 0.00000205 | ||||
| Deposit To App C... | 311808161 | 336 days ago | IN | 0.00010187 ETH | 0.00000191 | ||||
| Deposit To App C... | 311804527 | 336 days ago | IN | 0.00009709 ETH | 0.00000163 | ||||
| Deposit To App C... | 311803033 | 336 days ago | IN | 0.00009741 ETH | 0.00000165 | ||||
| Deposit To App C... | 311802881 | 336 days ago | IN | 0.00009741 ETH | 0.00000165 | ||||
| Deposit To App C... | 311802549 | 336 days ago | IN | 0.00009741 ETH | 0.00000165 | ||||
| Deposit To App C... | 311800879 | 336 days ago | IN | 0.00009584 ETH | 0.00000156 | ||||
| Deposit To App C... | 308782096 | 345 days ago | IN | 0.00010634 ETH | 0.00000214 | ||||
| Deposit To App C... | 308781365 | 345 days ago | IN | 0.00011512 ETH | 0.00000264 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 419421965 | 24 days ago | 0.00019377 ETH | ||||
| 419421965 | 24 days ago | 0.00019377 ETH | ||||
| 418843390 | 26 days ago | 0.00019404 ETH | ||||
| 418843390 | 26 days ago | 0.00019404 ETH | ||||
| 418552301 | 27 days ago | 0.00019835 ETH | ||||
| 418552301 | 27 days ago | 0.00019835 ETH | ||||
| 417508351 | 30 days ago | 0.00019385 ETH | ||||
| 417508351 | 30 days ago | 0.00019385 ETH | ||||
| 413681257 | 41 days ago | 0.00018874 ETH | ||||
| 413681257 | 41 days ago | 0.00018874 ETH | ||||
| 413616168 | 41 days ago | 0.00018868 ETH | ||||
| 413616168 | 41 days ago | 0.00018868 ETH | ||||
| 413332693 | 42 days ago | 0.00018862 ETH | ||||
| 413332693 | 42 days ago | 0.00018862 ETH | ||||
| 411722316 | 47 days ago | 0.00018865 ETH | ||||
| 411722316 | 47 days ago | 0.00018865 ETH | ||||
| 410978031 | 49 days ago | 0.00019222 ETH | ||||
| 410978031 | 49 days ago | 0.00019222 ETH | ||||
| 410538009 | 50 days ago | 0.0001888 ETH | ||||
| 410538009 | 50 days ago | 0.0001888 ETH | ||||
| 410532833 | 50 days ago | 0.0001888 ETH | ||||
| 410532833 | 50 days ago | 0.0001888 ETH | ||||
| 409907264 | 52 days ago | 0.00019925 ETH | ||||
| 409907264 | 52 days ago | 0.00019925 ETH | ||||
| 409293332 | 54 days ago | 0.00018932 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Vault
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 999999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.8.13;
import "lib/solmate/src/utils/SafeTransferLib.sol";
import "lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol";
import {Gauge} from "./Gauge.sol";
import {IConnector, IHub} from "./ConnectorPlug.sol";
// @todo: separate our connecter plugs
contract Vault is Gauge, IHub, Ownable2Step {
using SafeTransferLib for ERC20;
ERC20 public immutable token__;
struct UpdateLimitParams {
bool isLock;
address connector;
uint256 maxLimit;
uint256 ratePerSecond;
}
// connector => receiver => pendingUnlock
mapping(address => mapping(address => uint256)) public pendingUnlocks;
// connector => amount
mapping(address => uint256) public connectorPendingUnlocks;
// connector => lockLimitParams
mapping(address => LimitParams) _lockLimitParams;
// connector => unlockLimitParams
mapping(address => LimitParams) _unlockLimitParams;
error ConnectorUnavailable();
event LimitParamsUpdated(UpdateLimitParams[] updates);
event TokensDeposited(
address connector,
address depositor,
address receiver,
uint256 depositAmount
);
event PendingTokensTransferred(
address connector,
address receiver,
uint256 unlockedAmount,
uint256 pendingAmount
);
event TokensPending(
address connector,
address receiver,
uint256 pendingAmount,
uint256 totalPendingAmount
);
event TokensUnlocked(
address connector,
address receiver,
uint256 unlockedAmount
);
constructor(address token_) {
token__ = ERC20(token_);
}
function updateLimitParams(
UpdateLimitParams[] calldata updates_
) external onlyOwner {
for (uint256 i; i < updates_.length; i++) {
if (updates_[i].isLock) {
_consumePartLimit(0, _lockLimitParams[updates_[i].connector]); // to keep current limit in sync
_lockLimitParams[updates_[i].connector].maxLimit = updates_[i]
.maxLimit;
_lockLimitParams[updates_[i].connector]
.ratePerSecond = updates_[i].ratePerSecond;
} else {
_consumePartLimit(0, _unlockLimitParams[updates_[i].connector]); // to keep current limit in sync
_unlockLimitParams[updates_[i].connector].maxLimit = updates_[i]
.maxLimit;
_unlockLimitParams[updates_[i].connector]
.ratePerSecond = updates_[i].ratePerSecond;
}
}
emit LimitParamsUpdated(updates_);
}
function depositToAppChain(
address receiver_,
uint256 amount_,
uint256 msgGasLimit_,
address connector_
) external payable {
if (_lockLimitParams[connector_].maxLimit == 0)
revert ConnectorUnavailable();
_consumeFullLimit(amount_, _lockLimitParams[connector_]); // reverts on limit hit
token__.safeTransferFrom(msg.sender, address(this), amount_);
IConnector(connector_).outbound{value: msg.value}(
msgGasLimit_,
abi.encode(receiver_, amount_)
);
emit TokensDeposited(connector_, msg.sender, receiver_, amount_);
}
function unlockPendingFor(address receiver_, address connector_) external {
if (_unlockLimitParams[connector_].maxLimit == 0)
revert ConnectorUnavailable();
uint256 pendingUnlock = pendingUnlocks[connector_][receiver_];
(uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(
pendingUnlock,
_unlockLimitParams[connector_]
);
pendingUnlocks[connector_][receiver_] = pendingAmount;
connectorPendingUnlocks[connector_] -= consumedAmount;
token__.safeTransfer(receiver_, consumedAmount);
emit PendingTokensTransferred(
connector_,
receiver_,
consumedAmount,
pendingAmount
);
}
// receive inbound assuming connector called
function receiveInbound(bytes memory payload_) external override {
if (_unlockLimitParams[msg.sender].maxLimit == 0)
revert ConnectorUnavailable();
(address receiver, uint256 unlockAmount) = abi.decode(
payload_,
(address, uint256)
);
(uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(
unlockAmount,
_unlockLimitParams[msg.sender]
);
if (pendingAmount > 0) {
// add instead of overwrite to handle case where already pending amount is left
pendingUnlocks[msg.sender][receiver] += pendingAmount;
connectorPendingUnlocks[msg.sender] += pendingAmount;
emit TokensPending(
msg.sender,
receiver,
pendingAmount,
pendingUnlocks[msg.sender][receiver]
);
}
token__.safeTransfer(receiver, consumedAmount);
emit TokensUnlocked(msg.sender, receiver, consumedAmount);
}
function getMinFees(
address connector_,
uint256 msgGasLimit_
) external view returns (uint256 totalFees) {
return IConnector(connector_).getMinFees(msgGasLimit_);
}
function getCurrentLockLimit(
address connector_
) external view returns (uint256) {
return _getCurrentLimit(_lockLimitParams[connector_]);
}
function getCurrentUnlockLimit(
address connector_
) external view returns (uint256) {
return _getCurrentLimit(_unlockLimitParams[connector_]);
}
function getLockLimitParams(
address connector_
) external view returns (LimitParams memory) {
return _lockLimitParams[connector_];
}
function getUnlockLimitParams(
address connector_
) external view returns (LimitParams memory) {
return _unlockLimitParams[connector_];
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.0;
import "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
/*//////////////////////////////////////////////////////////////
ETH OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferETH(address to, uint256 amount) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
/*//////////////////////////////////////////////////////////////
ERC20 OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument.
mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}pragma solidity 0.8.13;
import "lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol";
import {ISocket} from "./interfaces/ISocket.sol";
import {IPlug} from "./interfaces/IPlug.sol";
interface IHub {
function receiveInbound(bytes memory payload_) external;
}
interface IConnector {
function outbound(
uint256 msgGasLimit_,
bytes memory payload_
) external payable;
function siblingChainSlug() external view returns (uint32);
function getMinFees(
uint256 msgGasLimit_
) external view returns (uint256 totalFees);
}
contract ConnectorPlug is IConnector, IPlug, Ownable2Step {
IHub public immutable hub__;
ISocket public immutable socket__;
uint32 public immutable siblingChainSlug;
error NotHub();
error NotSocket();
event ConnectorPlugDisconnected(address siblingPlug);
constructor(address hub_, address socket_, uint32 siblingChainSlug_) {
hub__ = IHub(hub_);
socket__ = ISocket(socket_);
siblingChainSlug = siblingChainSlug_;
}
function outbound(
uint256 msgGasLimit_,
bytes memory payload_
) external payable override {
if (msg.sender != address(hub__)) revert NotHub();
socket__.outbound{value: msg.value}(
siblingChainSlug,
msgGasLimit_,
bytes32(0),
bytes32(0),
payload_
);
}
function inbound(
uint32 /* siblingChainSlug_ */, // cannot be connected for any other slug, immutable variable
bytes calldata payload_
) external payable override {
if (msg.sender != address(socket__)) revert NotSocket();
hub__.receiveInbound(payload_);
}
function getMinFees(
uint256 msgGasLimit_
) external view override returns (uint256 totalFees) {
return
socket__.getMinFees(
msgGasLimit_,
64,
bytes32(0),
bytes32(0),
siblingChainSlug,
address(this)
);
}
function connect(
address siblingPlug_,
address switchboard_
) external onlyOwner {
socket__.connect(
siblingChainSlug,
siblingPlug_,
switchboard_,
switchboard_
);
}
function disconnect(address siblingPlug_) external onlyOwner {
socket__.connect(
siblingChainSlug,
siblingPlug_,
address(0),
address(0)
);
emit ConnectorPlugDisconnected(siblingPlug_);
}
}pragma solidity 0.8.13;
import "lib/solmate/src/utils/SafeTransferLib.sol";
import "lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol";
import {IExchangeRate} from "./ExchangeRate.sol";
import {Gauge} from "./Gauge.sol";
import {IConnector, IHub} from "./ConnectorPlug.sol";
import {IMintableERC20} from "./MintableToken.sol";
contract Controller is IHub, Gauge, Ownable2Step {
using SafeTransferLib for IMintableERC20;
IMintableERC20 public immutable token__;
IExchangeRate public exchangeRate__;
struct UpdateLimitParams {
bool isMint;
address connector;
uint256 maxLimit;
uint256 ratePerSecond;
}
// connector => totalLockedAmount
mapping(address => uint256) public connectorLockedAmounts;
// connector => mintLimitParams
mapping(address => LimitParams) _mintLimitParams;
// connector => burnLimitParams
mapping(address => LimitParams) _burnLimitParams;
// connector => receiver => amount
mapping(address => mapping(address => uint256)) public pendingMints;
// connector => amount
mapping(address => uint256) public connectorPendingMints;
uint256 public totalMinted;
error ConnectorUnavailable();
event ExchangeRateUpdated(address exchangeRate);
event LimitParamsUpdated(UpdateLimitParams[] updates);
event TokensWithdrawn(
address connector,
address withdrawer,
address receiver,
uint256 burnAmount
);
event PendingTokensMinted(
address connector,
address receiver,
uint256 mintAmount,
uint256 pendingAmount
);
event TokensPending(
address connecter,
address receiver,
uint256 pendingAmount,
uint256 totalPendingAmount
);
event TokensMinted(address connecter, address receiver, uint256 mintAmount);
constructor(address token_, address exchangeRate_) {
token__ = IMintableERC20(token_);
exchangeRate__ = IExchangeRate(exchangeRate_);
}
function updateExchangeRate(address exchangeRate_) external onlyOwner {
exchangeRate__ = IExchangeRate(exchangeRate_);
emit ExchangeRateUpdated(exchangeRate_);
}
function updateLimitParams(
UpdateLimitParams[] calldata updates_
) external onlyOwner {
for (uint256 i; i < updates_.length; i++) {
if (updates_[i].isMint) {
_consumePartLimit(0, _mintLimitParams[updates_[i].connector]); // to keep current limit in sync
_mintLimitParams[updates_[i].connector].maxLimit = updates_[i]
.maxLimit;
_mintLimitParams[updates_[i].connector]
.ratePerSecond = updates_[i].ratePerSecond;
} else {
_consumePartLimit(0, _burnLimitParams[updates_[i].connector]); // to keep current limit in sync
_burnLimitParams[updates_[i].connector].maxLimit = updates_[i]
.maxLimit;
_burnLimitParams[updates_[i].connector]
.ratePerSecond = updates_[i].ratePerSecond;
}
}
emit LimitParamsUpdated(updates_);
}
// do we throttle burn amount or unlock amount? burn for now
function withdrawFromAppChain(
address receiver_,
uint256 burnAmount_,
uint256 msgGasLimit_,
address connector_
) external payable {
if (_burnLimitParams[connector_].maxLimit == 0)
revert ConnectorUnavailable();
_consumeFullLimit(burnAmount_, _burnLimitParams[connector_]); // reverts on limit hit
totalMinted -= burnAmount_;
token__.burn(msg.sender, burnAmount_);
uint256 unlockAmount = exchangeRate__.getUnlockAmount(
burnAmount_,
connectorLockedAmounts[connector_]
);
connectorLockedAmounts[connector_] -= unlockAmount; // underflow revert expected
IConnector(connector_).outbound{value: msg.value}(
msgGasLimit_,
abi.encode(receiver_, unlockAmount)
);
emit TokensWithdrawn(connector_, msg.sender, receiver_, burnAmount_);
}
function mintPendingFor(address receiver_, address connector_) external {
if (_mintLimitParams[connector_].maxLimit == 0)
revert ConnectorUnavailable();
uint256 pendingMint = pendingMints[connector_][receiver_];
(uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(
pendingMint,
_mintLimitParams[connector_]
);
pendingMints[connector_][receiver_] = pendingAmount;
connectorPendingMints[connector_] -= consumedAmount;
totalMinted += consumedAmount;
token__.mint(receiver_, consumedAmount);
emit PendingTokensMinted(
connector_,
receiver_,
consumedAmount,
pendingAmount
);
}
// receive inbound assuming connector called
function receiveInbound(bytes memory payload_) external override {
if (_mintLimitParams[msg.sender].maxLimit == 0)
revert ConnectorUnavailable();
(address receiver, uint256 lockAmount) = abi.decode(
payload_,
(address, uint256)
);
connectorLockedAmounts[msg.sender] += lockAmount;
uint256 mintAmount = exchangeRate__.getMintAmount(
lockAmount,
connectorLockedAmounts[msg.sender]
);
(uint256 consumedAmount, uint256 pendingAmount) = _consumePartLimit(
mintAmount,
_mintLimitParams[msg.sender]
);
if (pendingAmount > 0) {
// add instead of overwrite to handle case where already pending amount is left
pendingMints[msg.sender][receiver] += pendingAmount;
connectorPendingMints[msg.sender] += pendingAmount;
emit TokensPending(
msg.sender,
receiver,
pendingAmount,
pendingMints[msg.sender][receiver]
);
}
totalMinted += consumedAmount;
token__.mint(receiver, consumedAmount);
emit TokensMinted(msg.sender, receiver, consumedAmount);
}
function getMinFees(
address connector_,
uint256 msgGasLimit_
) external view returns (uint256 totalFees) {
return IConnector(connector_).getMinFees(msgGasLimit_);
}
function getCurrentMintLimit(
address connector_
) external view returns (uint256) {
return _getCurrentLimit(_mintLimitParams[connector_]);
}
function getCurrentBurnLimit(
address connector_
) external view returns (uint256) {
return _getCurrentLimit(_burnLimitParams[connector_]);
}
function getMintLimitParams(
address connector_
) external view returns (LimitParams memory) {
return _mintLimitParams[connector_];
}
function getBurnLimitParams(
address connector_
) external view returns (LimitParams memory) {
return _burnLimitParams[connector_];
}
}pragma solidity 0.8.13;
interface IExchangeRate {
// not marked pure, may involve state interactions in future
function getMintAmount(
uint256 lockAmount,
uint256 totalLockedAmount
) external returns (uint256 mintAmount);
// not marked pure, may involve state interactions in future
function getUnlockAmount(
uint256 burnAmount,
uint256 totalLockedAmount
) external returns (uint256 unlockAmount);
}
contract ExchangeRate is IExchangeRate {
// chainId input needed? what else? slippage?
function getMintAmount(
uint256 lockAmount,
uint256 /* totalLockedAmount */
) external pure returns (uint256 mintAmount) {
return lockAmount;
}
function getUnlockAmount(
uint256 burnAmount,
uint256 /* totalLockedAmount */
) external pure returns (uint256 unlockAmount) {
return burnAmount;
}
}pragma solidity 0.8.13;
abstract contract Gauge {
struct LimitParams {
uint256 lastUpdateTimestamp;
uint256 ratePerSecond;
uint256 maxLimit;
uint256 lastUpdateLimit;
}
error AmountOutsideLimit();
function _getCurrentLimit(
LimitParams storage _params
) internal view returns (uint256 _limit) {
uint256 timeElapsed = block.timestamp - _params.lastUpdateTimestamp;
uint256 limitIncrease = timeElapsed * _params.ratePerSecond;
if (limitIncrease + _params.lastUpdateLimit > _params.maxLimit) {
_limit = _params.maxLimit;
} else {
_limit = limitIncrease + _params.lastUpdateLimit;
}
}
function _consumePartLimit(
uint256 amount_,
LimitParams storage _params
) internal returns (uint256 consumedAmount, uint256 pendingAmount) {
uint256 currentLimit = _getCurrentLimit(_params);
_params.lastUpdateTimestamp = block.timestamp;
if (currentLimit >= amount_) {
_params.lastUpdateLimit = currentLimit - amount_;
consumedAmount = amount_;
pendingAmount = 0;
} else {
_params.lastUpdateLimit = 0;
consumedAmount = currentLimit;
pendingAmount = amount_ - currentLimit;
}
}
function _consumeFullLimit(
uint256 amount_,
LimitParams storage _params
) internal {
uint256 currentLimit = _getCurrentLimit(_params);
if (currentLimit >= amount_) {
_params.lastUpdateTimestamp = block.timestamp;
_params.lastUpdateLimit = currentLimit - amount_;
} else {
revert AmountOutsideLimit();
}
}
}// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.13;
/**
* @title IPlug
* @notice Interface for a plug contract that executes the message received from a source chain.
*/
interface IPlug {
/**
* @dev this should be only executable by socket
* @notice executes the message received from source chain
* @notice It is expected to have original sender checks in the destination plugs using payload
* @param srcChainSlug_ chain slug of source
* @param payload_ the data which is needed by plug at inbound call on remote
*/
function inbound(
uint32 srcChainSlug_,
bytes calldata payload_
) external payable;
}// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.13;
/**
* @title ISocket
* @notice An interface for a cross-chain communication contract
* @dev This interface provides methods for transmitting and executing messages between chains,
* connecting a plug to a remote chain and setting up switchboards for the message transmission
* This interface also emits events for important operations such as message transmission, execution status,
* and plug connection
*/
interface ISocket {
/**
* @notice A struct containing fees required for message transmission and execution
* @param transmissionFees fees needed for transmission
* @param switchboardFees fees needed by switchboard
* @param executionFee fees needed for execution
*/
struct Fees {
uint128 transmissionFees;
uint128 executionFee;
uint128 switchboardFees;
}
/**
* @title MessageDetails
* @dev This struct defines the details of a message to be executed in a Decapacitor contract.
*/
struct MessageDetails {
// A unique identifier for the message.
bytes32 msgId;
// The fee to be paid for executing the message.
uint256 executionFee;
// The maximum amount of gas that can be used to execute the message.
uint256 minMsgGasLimit;
// The extra params which provides msg value and additional info needed for message exec
bytes32 executionParams;
// The payload data to be executed in the message.
bytes payload;
}
/**
* @title ExecutionDetails
* @dev This struct defines the execution details
*/
struct ExecutionDetails {
// packet id
bytes32 packetId;
// proposal count
uint256 proposalCount;
// gas limit needed to execute inbound
uint256 executionGasLimit;
// proof data required by the Decapacitor contract to verify the message's authenticity
bytes decapacitorProof;
// signature of executor
bytes signature;
}
/**
* @notice emits the message details when a new message arrives at outbound
* @param localChainSlug local chain slug
* @param localPlug local plug address
* @param dstChainSlug remote chain slug
* @param dstPlug remote plug address
* @param msgId message id packed with remoteChainSlug and nonce
* @param minMsgGasLimit gas limit needed to execute the inbound at remote
* @param payload the data which will be used by inbound at remote
*/
event MessageOutbound(
uint32 localChainSlug,
address localPlug,
uint32 dstChainSlug,
address dstPlug,
bytes32 msgId,
uint256 minMsgGasLimit,
bytes32 executionParams,
bytes32 transmissionParams,
bytes payload,
Fees fees
);
/**
* @notice emits the status of message after inbound call
* @param msgId msg id which is executed
*/
event ExecutionSuccess(bytes32 msgId);
/**
* @notice emits the config set by a plug for a remoteChainSlug
* @param plug address of plug on current chain
* @param siblingChainSlug sibling chain slug
* @param siblingPlug address of plug on sibling chain
* @param inboundSwitchboard inbound switchboard (select from registered options)
* @param outboundSwitchboard outbound switchboard (select from registered options)
* @param capacitor capacitor selected based on outbound switchboard
* @param decapacitor decapacitor selected based on inbound switchboard
*/
event PlugConnected(
address plug,
uint32 siblingChainSlug,
address siblingPlug,
address inboundSwitchboard,
address outboundSwitchboard,
address capacitor,
address decapacitor
);
/**
* @notice registers a message
* @dev Packs the message and includes it in a packet with capacitor
* @param remoteChainSlug_ the remote chain slug
* @param minMsgGasLimit_ the gas limit needed to execute the payload on remote
* @param payload_ the data which is needed by plug at inbound call on remote
*/
function outbound(
uint32 remoteChainSlug_,
uint256 minMsgGasLimit_,
bytes32 executionParams_,
bytes32 transmissionParams_,
bytes calldata payload_
) external payable returns (bytes32 msgId);
/**
* @notice executes a message
* @param executionDetails_ the packet details, proof and signature needed for message execution
* @param messageDetails_ the message details
*/
function execute(
ISocket.ExecutionDetails calldata executionDetails_,
ISocket.MessageDetails calldata messageDetails_
) external payable;
/**
* @notice sets the config specific to the plug
* @param siblingChainSlug_ the sibling chain slug
* @param siblingPlug_ address of plug present at sibling chain to call inbound
* @param inboundSwitchboard_ the address of switchboard to use for receiving messages
* @param outboundSwitchboard_ the address of switchboard to use for sending messages
*/
function connect(
uint32 siblingChainSlug_,
address siblingPlug_,
address inboundSwitchboard_,
address outboundSwitchboard_
) external;
/**
* @notice Retrieves the minimum fees required for a message with a specified gas limit and destination chain.
* @param minMsgGasLimit_ The gas limit of the message.
* @param remoteChainSlug_ The slug of the destination chain for the message.
* @param plug_ The address of the plug through which the message is sent.
* @return totalFees The minimum fees required for the specified message.
*/
function getMinFees(
uint256 minMsgGasLimit_,
uint256 payloadSize_,
bytes32 executionParams_,
bytes32 transmissionParams_,
uint32 remoteChainSlug_,
address plug_
) external view returns (uint256 totalFees);
/**
* @notice returns chain slug
* @return chainSlug current chain slug
*/
function chainSlug() external view returns (uint32 chainSlug);
}pragma solidity 0.8.13;
import "lib/solmate/src/tokens/ERC20.sol";
abstract contract IMintableERC20 is ERC20 {
function mint(address receiver_, uint256 amount_) external virtual;
function burn(address burner_, uint256 amount_) external virtual;
}
contract MintableToken is IMintableERC20 {
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_
) ERC20(name_, symbol_, decimals_) {}
function mint(address receiver_, uint256 amount_) external override {
_mint(receiver_, amount_);
}
function burn(address burner_, uint256 amount_) external override {
_burn(burner_, amount_);
}
}pragma solidity 0.8.13;
import "lib/solmate/src/tokens/ERC20.sol";
contract NonMintableToken is ERC20 {
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_,
uint256 totalSupply_
) ERC20(name_, symbol_, decimals_) {
_mint(msg.sender, totalSupply_);
}
}{
"optimizer": {
"enabled": true,
"runs": 999999
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"token_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AmountOutsideLimit","type":"error"},{"inputs":[],"name":"ConnectorUnavailable","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bool","name":"isLock","type":"bool"},{"internalType":"address","name":"connector","type":"address"},{"internalType":"uint256","name":"maxLimit","type":"uint256"},{"internalType":"uint256","name":"ratePerSecond","type":"uint256"}],"indexed":false,"internalType":"struct Vault.UpdateLimitParams[]","name":"updates","type":"tuple[]"}],"name":"LimitParamsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"connector","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"unlockedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"pendingAmount","type":"uint256"}],"name":"PendingTokensTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"connector","type":"address"},{"indexed":false,"internalType":"address","name":"depositor","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"depositAmount","type":"uint256"}],"name":"TokensDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"connector","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"pendingAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalPendingAmount","type":"uint256"}],"name":"TokensPending","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"connector","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"unlockedAmount","type":"uint256"}],"name":"TokensUnlocked","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"connectorPendingUnlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"uint256","name":"msgGasLimit_","type":"uint256"},{"internalType":"address","name":"connector_","type":"address"}],"name":"depositToAppChain","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"connector_","type":"address"}],"name":"getCurrentLockLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"connector_","type":"address"}],"name":"getCurrentUnlockLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"connector_","type":"address"}],"name":"getLockLimitParams","outputs":[{"components":[{"internalType":"uint256","name":"lastUpdateTimestamp","type":"uint256"},{"internalType":"uint256","name":"ratePerSecond","type":"uint256"},{"internalType":"uint256","name":"maxLimit","type":"uint256"},{"internalType":"uint256","name":"lastUpdateLimit","type":"uint256"}],"internalType":"struct Gauge.LimitParams","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"connector_","type":"address"},{"internalType":"uint256","name":"msgGasLimit_","type":"uint256"}],"name":"getMinFees","outputs":[{"internalType":"uint256","name":"totalFees","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"connector_","type":"address"}],"name":"getUnlockLimitParams","outputs":[{"components":[{"internalType":"uint256","name":"lastUpdateTimestamp","type":"uint256"},{"internalType":"uint256","name":"ratePerSecond","type":"uint256"},{"internalType":"uint256","name":"maxLimit","type":"uint256"},{"internalType":"uint256","name":"lastUpdateLimit","type":"uint256"}],"internalType":"struct Gauge.LimitParams","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"pendingUnlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"payload_","type":"bytes"}],"name":"receiveInbound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token__","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"address","name":"connector_","type":"address"}],"name":"unlockPendingFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"isLock","type":"bool"},{"internalType":"address","name":"connector","type":"address"},{"internalType":"uint256","name":"maxLimit","type":"uint256"},{"internalType":"uint256","name":"ratePerSecond","type":"uint256"}],"internalType":"struct Vault.UpdateLimitParams[]","name":"updates_","type":"tuple[]"}],"name":"updateLimitParams","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a06040523480156200001157600080fd5b5060405162001a3438038062001a348339810160408190526200003491620000cb565b6200003f3362000051565b6001600160a01b0316608052620000fd565b600180546001600160a01b031916905562000078816200007b602090811b62000ff217901c565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000de57600080fd5b81516001600160a01b0381168114620000f657600080fd5b9392505050565b6080516119066200012e600039600081816101ff0152818161055601528181610bcc0152610ebf01526119066000f3fe60806040526004361061010e5760003560e01c806379ba5097116100a55780638da5cb5b11610074578063e30c397811610059578063e30c397814610361578063f2b7c5cd1461038c578063f2fde38b146103ac57600080fd5b80638da5cb5b146103165780639b4cd9401461034157600080fd5b806379ba5097146102ae5780638367080f146102c357806384f289cc146102e3578063864f6a7a1461030357600080fd5b80634603f9f4116100e15780634603f9f4146101cd57806349eec51e146101ed578063715018a614610246578063755e1e241461025b57600080fd5b806310c56ed914610113578063186669e8146101355780632bc9c08a146101805780632fef4a8b146101a0575b600080fd5b34801561011f57600080fd5b5061013361012e366004611427565b6103cc565b005b34801561014157600080fd5b5061016d610150366004611518565b600260209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b34801561018c57600080fd5b5061013361019b366004611551565b6105db565b3480156101ac57600080fd5b5061016d6101bb3660046115c6565b60036020526000908152604090205481565b3480156101d957600080fd5b5061016d6101e83660046115c6565b6108d2565b3480156101f957600080fd5b506102217f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610177565b34801561025257600080fd5b50610133610906565b34801561026757600080fd5b5061027b6102763660046115c6565b61091a565b60405161017791908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b3480156102ba57600080fd5b506101336109a0565b3480156102cf57600080fd5b5061016d6102de3660046115e3565b610a5a565b3480156102ef57600080fd5b5061016d6102fe3660046115c6565b610af3565b61013361031136600461160f565b610b21565b34801561032257600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610221565b34801561034d57600080fd5b5061027b61035c3660046115c6565b610d12565b34801561036d57600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff16610221565b34801561039857600080fd5b506101336103a7366004611518565b610d98565b3480156103b857600080fd5b506101336103c73660046115c6565b610f42565b336000908152600560205260408120600201549003610417576040517fb1efb84a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808280602001905181019061042e9190611659565b336000908152600560205260408120929450909250908190610451908490611067565b9092509050801561053c5733600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff881684529091528120805483929061049c9084906116b6565b909155505033600090815260036020526040812080548392906104c09084906116b6565b909155505033600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff891680855290835292819020548151948552918401929092528282018490526060830152517ffef75efa635291b302f2c3dfcc6ec92874e699d186cee8bd68c36c86ad35232c9181900360800190a15b61057d73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001685846110bb565b6040805133815273ffffffffffffffffffffffffffffffffffffffff861660208201529081018390527fece684e11f49f06d351439e63189ad1703238b8040d90cf994901ca2b3da8d44906060015b60405180910390a15050505050565b6105e3611190565b60005b8181101561089457828282818110610600576106006116ce565b6106169260206080909202019081019150611712565b1561077c5761068d600060046000868686818110610636576106366116ce565b905060800201602001602081019061064e91906115c6565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611067565b50508282828181106106a1576106a16116ce565b90506080020160400135600460008585858181106106c1576106c16116ce565b90506080020160200160208101906106d991906115c6565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002060020155828282818110610715576107156116ce565b9050608002016060013560046000858585818110610735576107356116ce565b905060800201602001602081019061074d91906115c6565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002060010155610882565b610797600060056000868686818110610636576106366116ce565b50508282828181106107ab576107ab6116ce565b90506080020160400135600560008585858181106107cb576107cb6116ce565b90506080020160200160208101906107e391906115c6565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000206002015582828281811061081f5761081f6116ce565b905060800201606001356005600085858581811061083f5761083f6116ce565b905060800201602001602081019061085791906115c6565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020600101555b8061088c8161172d565b9150506105e6565b507f19863caed14ed012a54f927e56250018b7ac3c04fd197e0edf23369f75a6ccd482826040516108c6929190611765565b60405180910390a15050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260046020526040812061090090611211565b92915050565b61090e611190565b6109186000611278565b565b6109456040518060800160405280600081526020016000815260200160008152602001600081525090565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260046020908152604091829020825160808101845281548152600182015492810192909252600281015492820192909252600390910154606082015290565b600154339073ffffffffffffffffffffffffffffffffffffffff168114610a4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610a5781611278565b50565b6040517f89c1cf9a0000000000000000000000000000000000000000000000000000000081526004810182905260009073ffffffffffffffffffffffffffffffffffffffff8416906389c1cf9a90602401602060405180830381865afa158015610ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aec91906117e8565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040812061090090611211565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600460205260408120600201549003610b82576040517fb1efb84a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600460205260409020610bb29084906112a9565b610bf473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333086611306565b8073ffffffffffffffffffffffffffffffffffffffff16631cbdf12b34848787604051602001610c4692919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401610c72929190611801565b6000604051808303818588803b158015610c8b57600080fd5b505af1158015610c9f573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8087168252336020830152891691810191909152606081018790527f9474e087d8a0e83962ac44e292b4aba027426203ea66adfb1dd9f65795ff599a93506080019150610d049050565b60405180910390a150505050565b610d3d6040518060800160405280600081526020016000815260200160008152602001600081525090565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260056020908152604091829020825160808101845281548152600182015492810192909252600281015492820192909252600390910154606082015290565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600560205260408120600201549003610df9576040517fb1efb84a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8082166000818152600260209081526040808320948716835293815283822054928252600590529182209091908190610e48908490611067565b73ffffffffffffffffffffffffffffffffffffffff8087166000818152600260209081526040808320948c168352938152838220859055918152600390915290812080549395509193508492610e9f90849061187c565b90915550610ee6905073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001686846110bb565b6040805173ffffffffffffffffffffffffffffffffffffffff808716825287166020820152908101839052606081018290527fc77b48bb4899bc689b5733d1b7b8bfc0f70e7660295ad5f94841902db16ddae2906080016105cc565b610f4a611190565b6001805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155610fad60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080600061107584611211565b428555905084811061109c5761108b858261187c565b6003850155849250600091506110b3565b600060038501559150816110b0818661187c565b91505b509250929050565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061118a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610a45565b50505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610918576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a45565b80546000908190611222904261187c565b905060008360010154826112369190611893565b9050836002015484600301548261124d91906116b6565b111561125f5783600201549250611271565b600384015461126e90826116b6565b92505b5050919050565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610a5781610ff2565b60006112b482611211565b90508281106112d4574282556112ca838261187c565b6003830155505050565b6040517f47ebad2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806113f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610a45565b5050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561143957600080fd5b813567ffffffffffffffff8082111561145157600080fd5b818401915084601f83011261146557600080fd5b813581811115611477576114776113f8565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156114bd576114bd6113f8565b816040528281528760208487010111156114d657600080fd5b826020860160208301376000928101602001929092525095945050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a5757600080fd5b6000806040838503121561152b57600080fd5b8235611536816114f6565b91506020830135611546816114f6565b809150509250929050565b6000806020838503121561156457600080fd5b823567ffffffffffffffff8082111561157c57600080fd5b818501915085601f83011261159057600080fd5b81358181111561159f57600080fd5b8660208260071b85010111156115b457600080fd5b60209290920196919550909350505050565b6000602082840312156115d857600080fd5b8135610aec816114f6565b600080604083850312156115f657600080fd5b8235611601816114f6565b946020939093013593505050565b6000806000806080858703121561162557600080fd5b8435611630816114f6565b93506020850135925060408501359150606085013561164e816114f6565b939692955090935050565b6000806040838503121561166c57600080fd5b8251611677816114f6565b6020939093015192949293505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156116c9576116c9611687565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8035801515811461170d57600080fd5b919050565b60006020828403121561172457600080fd5b610aec826116fd565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361175e5761175e611687565b5060010190565b6020808252818101839052600090604080840186845b878110156117db5761178c826116fd565b151583528482013561179d816114f6565b73ffffffffffffffffffffffffffffffffffffffff16838601528184013584840152606080830135908401526080928301929091019060010161177b565b5090979650505050505050565b6000602082840312156117fa57600080fd5b5051919050565b82815260006020604081840152835180604085015260005b8181101561183557858101830151858201606001528201611819565b81811115611847576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201606001949350505050565b60008282101561188e5761188e611687565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156118cb576118cb611687565b50029056fea2646970667358221220f28ae64d41d2b0fb2bf9d301115284a5af4d0cb5adcf69bce4ea69a815f7894e64736f6c634300080d0033000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8
Deployed Bytecode
0x60806040526004361061010e5760003560e01c806379ba5097116100a55780638da5cb5b11610074578063e30c397811610059578063e30c397814610361578063f2b7c5cd1461038c578063f2fde38b146103ac57600080fd5b80638da5cb5b146103165780639b4cd9401461034157600080fd5b806379ba5097146102ae5780638367080f146102c357806384f289cc146102e3578063864f6a7a1461030357600080fd5b80634603f9f4116100e15780634603f9f4146101cd57806349eec51e146101ed578063715018a614610246578063755e1e241461025b57600080fd5b806310c56ed914610113578063186669e8146101355780632bc9c08a146101805780632fef4a8b146101a0575b600080fd5b34801561011f57600080fd5b5061013361012e366004611427565b6103cc565b005b34801561014157600080fd5b5061016d610150366004611518565b600260209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b34801561018c57600080fd5b5061013361019b366004611551565b6105db565b3480156101ac57600080fd5b5061016d6101bb3660046115c6565b60036020526000908152604090205481565b3480156101d957600080fd5b5061016d6101e83660046115c6565b6108d2565b3480156101f957600080fd5b506102217f000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc881565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610177565b34801561025257600080fd5b50610133610906565b34801561026757600080fd5b5061027b6102763660046115c6565b61091a565b60405161017791908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b3480156102ba57600080fd5b506101336109a0565b3480156102cf57600080fd5b5061016d6102de3660046115e3565b610a5a565b3480156102ef57600080fd5b5061016d6102fe3660046115c6565b610af3565b61013361031136600461160f565b610b21565b34801561032257600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610221565b34801561034d57600080fd5b5061027b61035c3660046115c6565b610d12565b34801561036d57600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff16610221565b34801561039857600080fd5b506101336103a7366004611518565b610d98565b3480156103b857600080fd5b506101336103c73660046115c6565b610f42565b336000908152600560205260408120600201549003610417576040517fb1efb84a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808280602001905181019061042e9190611659565b336000908152600560205260408120929450909250908190610451908490611067565b9092509050801561053c5733600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff881684529091528120805483929061049c9084906116b6565b909155505033600090815260036020526040812080548392906104c09084906116b6565b909155505033600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff891680855290835292819020548151948552918401929092528282018490526060830152517ffef75efa635291b302f2c3dfcc6ec92874e699d186cee8bd68c36c86ad35232c9181900360800190a15b61057d73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc81685846110bb565b6040805133815273ffffffffffffffffffffffffffffffffffffffff861660208201529081018390527fece684e11f49f06d351439e63189ad1703238b8040d90cf994901ca2b3da8d44906060015b60405180910390a15050505050565b6105e3611190565b60005b8181101561089457828282818110610600576106006116ce565b6106169260206080909202019081019150611712565b1561077c5761068d600060046000868686818110610636576106366116ce565b905060800201602001602081019061064e91906115c6565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611067565b50508282828181106106a1576106a16116ce565b90506080020160400135600460008585858181106106c1576106c16116ce565b90506080020160200160208101906106d991906115c6565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002060020155828282818110610715576107156116ce565b9050608002016060013560046000858585818110610735576107356116ce565b905060800201602001602081019061074d91906115c6565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002060010155610882565b610797600060056000868686818110610636576106366116ce565b50508282828181106107ab576107ab6116ce565b90506080020160400135600560008585858181106107cb576107cb6116ce565b90506080020160200160208101906107e391906115c6565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000206002015582828281811061081f5761081f6116ce565b905060800201606001356005600085858581811061083f5761083f6116ce565b905060800201602001602081019061085791906115c6565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020600101555b8061088c8161172d565b9150506105e6565b507f19863caed14ed012a54f927e56250018b7ac3c04fd197e0edf23369f75a6ccd482826040516108c6929190611765565b60405180910390a15050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260046020526040812061090090611211565b92915050565b61090e611190565b6109186000611278565b565b6109456040518060800160405280600081526020016000815260200160008152602001600081525090565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260046020908152604091829020825160808101845281548152600182015492810192909252600281015492820192909252600390910154606082015290565b600154339073ffffffffffffffffffffffffffffffffffffffff168114610a4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e6572000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610a5781611278565b50565b6040517f89c1cf9a0000000000000000000000000000000000000000000000000000000081526004810182905260009073ffffffffffffffffffffffffffffffffffffffff8416906389c1cf9a90602401602060405180830381865afa158015610ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aec91906117e8565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040812061090090611211565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600460205260408120600201549003610b82576040517fb1efb84a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000908152600460205260409020610bb29084906112a9565b610bf473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc816333086611306565b8073ffffffffffffffffffffffffffffffffffffffff16631cbdf12b34848787604051602001610c4692919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401610c72929190611801565b6000604051808303818588803b158015610c8b57600080fd5b505af1158015610c9f573d6000803e3d6000fd5b50506040805173ffffffffffffffffffffffffffffffffffffffff8087168252336020830152891691810191909152606081018790527f9474e087d8a0e83962ac44e292b4aba027426203ea66adfb1dd9f65795ff599a93506080019150610d049050565b60405180910390a150505050565b610d3d6040518060800160405280600081526020016000815260200160008152602001600081525090565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260056020908152604091829020825160808101845281548152600182015492810192909252600281015492820192909252600390910154606082015290565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600560205260408120600201549003610df9576040517fb1efb84a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8082166000818152600260209081526040808320948716835293815283822054928252600590529182209091908190610e48908490611067565b73ffffffffffffffffffffffffffffffffffffffff8087166000818152600260209081526040808320948c168352938152838220859055918152600390915290812080549395509193508492610e9f90849061187c565b90915550610ee6905073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc81686846110bb565b6040805173ffffffffffffffffffffffffffffffffffffffff808716825287166020820152908101839052606081018290527fc77b48bb4899bc689b5733d1b7b8bfc0f70e7660295ad5f94841902db16ddae2906080016105cc565b610f4a611190565b6001805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155610fad60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080600061107584611211565b428555905084811061109c5761108b858261187c565b6003850155849250600091506110b3565b600060038501559150816110b0818661187c565b91505b509250929050565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061118a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610a45565b50505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610918576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a45565b80546000908190611222904261187c565b905060008360010154826112369190611893565b9050836002015484600301548261124d91906116b6565b111561125f5783600201549250611271565b600384015461126e90826116b6565b92505b5050919050565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610a5781610ff2565b60006112b482611211565b90508281106112d4574282556112ca838261187c565b6003830155505050565b6040517f47ebad2000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806113f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610a45565b5050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561143957600080fd5b813567ffffffffffffffff8082111561145157600080fd5b818401915084601f83011261146557600080fd5b813581811115611477576114776113f8565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156114bd576114bd6113f8565b816040528281528760208487010111156114d657600080fd5b826020860160208301376000928101602001929092525095945050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a5757600080fd5b6000806040838503121561152b57600080fd5b8235611536816114f6565b91506020830135611546816114f6565b809150509250929050565b6000806020838503121561156457600080fd5b823567ffffffffffffffff8082111561157c57600080fd5b818501915085601f83011261159057600080fd5b81358181111561159f57600080fd5b8660208260071b85010111156115b457600080fd5b60209290920196919550909350505050565b6000602082840312156115d857600080fd5b8135610aec816114f6565b600080604083850312156115f657600080fd5b8235611601816114f6565b946020939093013593505050565b6000806000806080858703121561162557600080fd5b8435611630816114f6565b93506020850135925060408501359150606085013561164e816114f6565b939692955090935050565b6000806040838503121561166c57600080fd5b8251611677816114f6565b6020939093015192949293505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156116c9576116c9611687565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8035801515811461170d57600080fd5b919050565b60006020828403121561172457600080fd5b610aec826116fd565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361175e5761175e611687565b5060010190565b6020808252818101839052600090604080840186845b878110156117db5761178c826116fd565b151583528482013561179d816114f6565b73ffffffffffffffffffffffffffffffffffffffff16838601528184013584840152606080830135908401526080928301929091019060010161177b565b5090979650505050505050565b6000602082840312156117fa57600080fd5b5051919050565b82815260006020604081840152835180604085015260005b8181101561183557858101830151858201606001528201611819565b81811115611847576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201606001949350505050565b60008282101561188e5761188e611687565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156118cb576118cb611687565b50029056fea2646970667358221220f28ae64d41d2b0fb2bf9d301115284a5af4d0cb5adcf69bce4ea69a815f7894e64736f6c634300080d0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8
-----Decoded View---------------
Arg [0] : token_ (address): 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$1,203.31
Net Worth in ETH
0.522506
Token Allocations
USDC.E
98.64%
ETH
0.78%
USDC
0.58%
Multichain Portfolio | 35 Chains
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.