ERC-4626
Source Code
Overview
Max Total Supply
8,670,415.340092462 SATS
Holders
20 (0.00%)
Transfers
-
0
Market
Price
$0.00 @ 0.000000 ETH (+0.36%)
Onchain Market Cap
$7,863.52
Circulating Supply Market Cap
$0.00
Other Info
Token Contract (WITH 18 Decimals)
Loading...
Loading
Loading...
Loading
Loading...
Loading
| # | Exchange | Pair | Price | 24H Volume | % Volume |
|---|
Contract Name:
Satoshi
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 20000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // Copyright (c) 2024 [email protected] /* Make SATS the Currency for billions 1 SATS backed by 1 Satoshi, SATS is fractionalised tBTC. 1tBTC = 100M SATS like how Satoshi was intended. This contract is free, immutable and permissionless. Fun Fact: === Satoshi Nakamoto is most likely into buddism. Sat is Sanskirt word in buddism means "Truth", also a buddist numeric value of 0.00000001 (10^-8) In ancient texts, fusion words based on Sat refer to "Universal Spirit, Universal Principle, Being, Soul of the World, Brahman" 1BTC = 100_000_000 // Buddism numeric system for small numbers 0.00000001 SAT 沙 0.00000000_1 塵 0.00000000_01 埃 0.00000000_001 MINI-SAT 渺 0.00000000_0001 漠 0.00000000_00001 模糊 0.00000000_00000_1 逡巡 0.00000000_00000_01 須臾 0.00000000_00000_001 瞬息 0.00000000_00000_0001 彈指 0.00000000_00000_00001 殺那 Shortest moment of time. tBTC Native contract deploy across chains === Ethereum 0x18084fba666a33d37592fa2633fd49a74dd93a88 Arbitrum 0x6c84a8f1c29108f47a79964b5fe888d4f4d0de40 Optimism 0x6c84a8f1c29108f47a79964b5fe888d4f4d0de40 Polygon 0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b Base 0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b Sepolia 0x517f2982701695D4E52f1ECFBEf3ba31Df470161 Solana 6DNSN2BJsaPFdFFc1zP37kkeNe4Usc1Sqkzr9C9vPWcU */ pragma solidity ^0.8.24; import { ERC20, ERC4626, FixedPointMathLib, SafeTransferLib } from 'solmate/src/mixins/ERC4626.sol'; import { ReentrancyGuard } from 'solmate/src/utils/ReentrancyGuard.sol'; /// @title Satoshi Vault Contract /// @notice Implements a vault for tBTC token where 1 tBTC equals 1e8 SATS (Satoshis). /// This contract allows depositing and withdrawing tBTC in a way that represents these transactions in SATS, managing the conversion and keeping track of the net flow of tBTC within the contract. contract Satoshi is ReentrancyGuard, ERC4626 { using FixedPointMathLib for uint256; using SafeTransferLib for ERC20; error InvalidAddress(); /// @notice The net flow of tBTC tokens within the contract. uint256 public netFlow; uint256 public constant SAT = 1e8; uint256 public constant WAD = 1e18; modifier validAddress(address _address) { _validAddress(_address); _; } /// @dev Initializes the Satoshi vault contract with tBTC as the underlying asset. /// @param _tBTC The ERC20 token address of tBTC to be used as the underlying asset. /// @param _name The name of the vault token. /// @param _symbol The symbol of the vault token. constructor( ERC20 _tBTC, string memory _name, string memory _symbol ) ERC4626(_tBTC, _name, _symbol) {} /// @notice Calculates the total assets under management in tBTC. /// @return The total amount of tBTC managed by the vault. function totalAssets() public view override returns (uint256) { return netFlow; } /// @notice Deposits tBTC into the vault in exchange for vault shares. /// @dev Overrides the deposit function of ERC4626 to include reentrancy protection. /// @param assets The amount of tBTC to deposit. /// @param receiver The address to receive the vault shares. /// @return shares The amount of vault shares issued for the deposit. function deposit( uint256 assets, address receiver ) public override nonReentrant validAddress(receiver) returns (uint256 shares) { return super.deposit(assets, receiver); } /// @notice Mints vault shares in exchange for tBTC. /// @dev Overrides the mint function of ERC4626 to include reentrancy protection. /// @param shares The amount of shares to mint. /// @param receiver The address to receive the minted shares. /// @return assets The amount of tBTC used to mint the shares. function mint( uint256 shares, address receiver ) public override nonReentrant validAddress(receiver) returns (uint256 assets) { shares = (shares / SAT) * SAT; // Round down to the nearest 1e8 SATS. return super.mint(shares, receiver); } /// @notice Withdraws tBTC from the vault in exchange for vault shares. /// @dev Overrides the withdraw function of ERC4626 to include reentrancy protection. /// @param assets The amount of tBTC to withdraw. /// @param receiver The address to receive the tBTC. /// @param owner The address owning the shares being withdrawn. /// @return shares The amount of vault shares burned for the withdrawal. function withdraw( uint256 assets, address receiver, address owner ) public override nonReentrant validAddress(receiver) returns (uint256 shares) { return super.withdraw(assets, receiver, owner); } /// @notice Redeems vault shares in exchange for tBTC. /// @dev Overrides the redeem function of ERC4626 to include reentrancy protection. /// @param shares The amount of shares to redeem. /// @param receiver The address to receive the tBTC. /// @param owner The address owning the shares being redeemed. /// @return assets The amount of tBTC given in exchange for the shares. function redeem( uint256 shares, address receiver, address owner ) public override nonReentrant validAddress(receiver) returns (uint256 assets) { shares = (shares / SAT) * SAT; // Round down to the nearest 1e8 SATS. return super.redeem(shares, receiver, owner); } /// @notice Converts a specific amount of tBTC to its equivalent amount in vault shares. /// @dev Provides an optimized gas calculation for share conversion. /// @param assets The amount of tBTC to be converted. /// @return The equivalent amount of shares. function convertToShares( uint256 assets ) public view override returns (uint256) { uint256 supply = totalSupply; // Optimization to save gas. return supply == 0 ? assets * SAT : assets.mulDivDown(supply, totalAssets()); } /// @notice Converts a specific amount of shares to its equivalent amount in tBTC. /// @dev Provides an optimized gas calculation for asset conversion. /// @param shares The amount of shares to be converted. /// @return The equivalent amount of tBTC. function convertToAssets( uint256 shares ) public view override returns (uint256) { shares = (shares / SAT) * SAT; // Round down to the nearest 1e8 SATS. uint256 supply = totalSupply; // Optimization to save gas. return supply == 0 ? shares / SAT : shares.mulDivDown(totalAssets(), supply); } /// @notice Calculates the amount of tBTC that would be obtained by minting a specific amount of shares. /// @dev Provides an optimized gas calculation for mint preview. /// @param shares The amount of shares to be minted. /// @return The equivalent amount of tBTC that would be obtained. function previewMint(uint256 shares) public view override returns (uint256) { shares = (shares / SAT) * SAT; // Round down to the nearest 1e8 SATS. uint256 supply = totalSupply; // Optimization to save gas. return supply == 0 ? shares / SAT : shares.mulDivUp(totalAssets(), supply); } /// @notice Calculates the amount of shares that would be needed to withdraw a specific amount of tBTC. /// @dev Provides an optimized gas calculation for withdraw preview. /// @param assets The amount of tBTC to be withdrawn. /// @return The equivalent amount of shares needed. function previewWithdraw( uint256 assets ) public view override returns (uint256) { uint256 supply = totalSupply; // Optimization to save gas. return supply == 0 ? assets * SAT : assets.mulDivUp(supply, totalAssets()); } /// @dev Adjusts the netFlow variable upon withdrawal. /// @param assets The amount of tBTC being withdrawn. function beforeWithdraw(uint256 assets, uint256) internal override { netFlow -= assets; } /// @dev Adjusts the netFlow variable upon deposit. /// @param assets The amount of tBTC being deposited. function afterDeposit(uint256 assets, uint256) internal override { netFlow += assets; } /// @notice Returns the current price per share in terms of tBTC. /// @return The price of one vault share in tBTC. function pricePerShare() public view returns (uint256) { return convertToAssets(WAD); } function _validAddress(address _address) internal pure { if (_address == address(0)) revert InvalidAddress(); } }
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
import {SafeTransferLib} from "../utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "../utils/FixedPointMathLib.sol";
/// @notice Minimal ERC4626 tokenized Vault implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/mixins/ERC4626.sol)
abstract contract ERC4626 is ERC20 {
using SafeTransferLib for ERC20;
using FixedPointMathLib for uint256;
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed caller,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/*//////////////////////////////////////////////////////////////
IMMUTABLES
//////////////////////////////////////////////////////////////*/
ERC20 public immutable asset;
constructor(
ERC20 _asset,
string memory _name,
string memory _symbol
) ERC20(_name, _symbol, _asset.decimals()) {
asset = _asset;
}
/*//////////////////////////////////////////////////////////////
DEPOSIT/WITHDRAWAL LOGIC
//////////////////////////////////////////////////////////////*/
function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) {
// Check for rounding error since we round down in previewDeposit.
require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");
// Need to transfer before minting or ERC777s could reenter.
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
afterDeposit(assets, shares);
}
function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) {
assets = previewMint(shares); // No need to check for rounding error, previewMint rounds up.
// Need to transfer before minting or ERC777s could reenter.
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
afterDeposit(assets, shares);
}
function withdraw(
uint256 assets,
address receiver,
address owner
) public virtual returns (uint256 shares) {
shares = previewWithdraw(assets); // No need to check for rounding error, previewWithdraw rounds up.
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
beforeWithdraw(assets, shares);
_burn(owner, shares);
emit Withdraw(msg.sender, receiver, owner, assets, shares);
asset.safeTransfer(receiver, assets);
}
function redeem(
uint256 shares,
address receiver,
address owner
) public virtual returns (uint256 assets) {
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
// Check for rounding error since we round down in previewRedeem.
require((assets = previewRedeem(shares)) != 0, "ZERO_ASSETS");
beforeWithdraw(assets, shares);
_burn(owner, shares);
emit Withdraw(msg.sender, receiver, owner, assets, shares);
asset.safeTransfer(receiver, assets);
}
/*//////////////////////////////////////////////////////////////
ACCOUNTING LOGIC
//////////////////////////////////////////////////////////////*/
function totalAssets() public view virtual returns (uint256);
function convertToShares(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets());
}
function convertToAssets(uint256 shares) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply);
}
function previewDeposit(uint256 assets) public view virtual returns (uint256) {
return convertToShares(assets);
}
function previewMint(uint256 shares) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? shares : shares.mulDivUp(totalAssets(), supply);
}
function previewWithdraw(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? assets : assets.mulDivUp(supply, totalAssets());
}
function previewRedeem(uint256 shares) public view virtual returns (uint256) {
return convertToAssets(shares);
}
/*//////////////////////////////////////////////////////////////
DEPOSIT/WITHDRAWAL LIMIT LOGIC
//////////////////////////////////////////////////////////////*/
function maxDeposit(address) public view virtual returns (uint256) {
return type(uint256).max;
}
function maxMint(address) public view virtual returns (uint256) {
return type(uint256).max;
}
function maxWithdraw(address owner) public view virtual returns (uint256) {
return convertToAssets(balanceOf[owner]);
}
function maxRedeem(address owner) public view virtual returns (uint256) {
return balanceOf[owner];
}
/*//////////////////////////////////////////////////////////////
INTERNAL HOOKS LOGIC
//////////////////////////////////////////////////////////////*/
function beforeWithdraw(uint256 assets, uint256 shares) internal virtual {}
function afterDeposit(uint256 assets, uint256 shares) internal virtual {}
}// 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;
/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
/*//////////////////////////////////////////////////////////////
SIMPLIFIED FIXED POINT OPERATIONS
//////////////////////////////////////////////////////////////*/
uint256 internal constant MAX_UINT256 = 2**256 - 1;
uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.
function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
}
function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
}
function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
}
function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
}
/*//////////////////////////////////////////////////////////////
LOW LEVEL FIXED POINT OPERATIONS
//////////////////////////////////////////////////////////////*/
function mulDivDown(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
// Divide x * y by the denominator.
z := div(mul(x, y), denominator)
}
}
function mulDivUp(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
// If x * y modulo the denominator is strictly greater than 0,
// 1 is added to round up the division of x * y by the denominator.
z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
}
}
function rpow(
uint256 x,
uint256 n,
uint256 scalar
) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
switch x
case 0 {
switch n
case 0 {
// 0 ** 0 = 1
z := scalar
}
default {
// 0 ** n = 0
z := 0
}
}
default {
switch mod(n, 2)
case 0 {
// If n is even, store scalar in z for now.
z := scalar
}
default {
// If n is odd, store x in z for now.
z := x
}
// Shifting right by 1 is like dividing by 2.
let half := shr(1, scalar)
for {
// Shift n right by 1 before looping to halve it.
n := shr(1, n)
} n {
// Shift n right by 1 each iteration to halve it.
n := shr(1, n)
} {
// Revert immediately if x ** 2 would overflow.
// Equivalent to iszero(eq(div(xx, x), x)) here.
if shr(128, x) {
revert(0, 0)
}
// Store x squared.
let xx := mul(x, x)
// Round to the nearest number.
let xxRound := add(xx, half)
// Revert if xx + half overflowed.
if lt(xxRound, xx) {
revert(0, 0)
}
// Set x to scaled xxRound.
x := div(xxRound, scalar)
// If n is even:
if mod(n, 2) {
// Compute z * x.
let zx := mul(z, x)
// If z * x overflowed:
if iszero(eq(div(zx, x), z)) {
// Revert if x is non-zero.
if iszero(iszero(x)) {
revert(0, 0)
}
}
// Round to the nearest number.
let zxRound := add(zx, half)
// Revert if zx + half overflowed.
if lt(zxRound, zx) {
revert(0, 0)
}
// Return properly scaled zxRound.
z := div(zxRound, scalar)
}
}
}
}
}
/*//////////////////////////////////////////////////////////////
GENERAL NUMBER UTILITIES
//////////////////////////////////////////////////////////////*/
function sqrt(uint256 x) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
let y := x // We start y at x, which will help us make our initial estimate.
z := 181 // The "correct" value is 1, but this saves a multiplication later.
// This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
// start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.
// We check y >= 2^(k + 8) but shift right by k bits
// each branch to ensure that if x >= 256, then y >= 256.
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
y := shr(128, y)
z := shl(64, z)
}
if iszero(lt(y, 0x1000000000000000000)) {
y := shr(64, y)
z := shl(32, z)
}
if iszero(lt(y, 0x10000000000)) {
y := shr(32, y)
z := shl(16, z)
}
if iszero(lt(y, 0x1000000)) {
y := shr(16, y)
z := shl(8, z)
}
// Goal was to get z*z*y within a small factor of x. More iterations could
// get y in a tighter range. Currently, we will have y in [256, 256*2^16).
// We ensured y >= 256 so that the relative difference between y and y+1 is small.
// That's not possible if x < 256 but we can just verify those cases exhaustively.
// Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.
// Correctness can be checked exhaustively for x < 256, so we assume y >= 256.
// Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.
// For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range
// (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.
// Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate
// sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.
// There is no overflow risk here since y < 2^136 after the first branch above.
z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.
// Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
// If x+1 is a perfect square, the Babylonian method cycles between
// floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.
// See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
// Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.
// If you don't care whether the floor or ceil square root is returned, you can remove this statement.
z := sub(z, lt(div(x, z), z))
}
}
function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Mod x by y. Note this will return
// 0 instead of reverting if y is zero.
z := mod(x, y)
}
}
function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
/// @solidity memory-safe-assembly
assembly {
// Divide x by y. Note this will return
// 0 instead of reverting if y is zero.
r := div(x, y)
}
}
function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Add 1 to x * y if x % y > 0. Note this will
// return 0 instead of reverting if y is zero.
z := add(gt(mod(x, y), 0), div(x, y))
}
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
uint256 private locked = 1;
modifier nonReentrant() virtual {
require(locked == 1, "REENTRANCY");
locked = 2;
_;
locked = 1;
}
}// 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");
}
}{
"evmVersion": "paris",
"optimizer": {
"enabled": true,
"runs": 20000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract ERC20","name":"_tBTC","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","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":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","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":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SAT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WAD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","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":"address","name":"","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","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":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"netFlow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricePerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
61010060405260016000553480156200001757600080fd5b50604051620021eb380380620021eb8339810160408190526200003a916200025b565b8282828181846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200007e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a49190620002e5565b6001620000b28482620003a2565b506002620000c18382620003a2565b5060ff81166080524660a052620000d7620000f7565b60c0525050506001600160a01b0390921660e05250620004ec9350505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60016040516200012b91906200046e565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001bb57600080fd5b81516001600160401b0380821115620001d857620001d862000193565b604051601f8301601f19908116603f0116810190828211818310171562000203576200020362000193565b81604052838152602092508660208588010111156200022157600080fd5b600091505b8382101562000245578582018301518183018401529082019062000226565b6000602085830101528094505050505092915050565b6000806000606084860312156200027157600080fd5b83516001600160a01b03811681146200028957600080fd5b60208501519093506001600160401b0380821115620002a757600080fd5b620002b587838801620001a9565b93506040860151915080821115620002cc57600080fd5b50620002db86828701620001a9565b9150509250925092565b600060208284031215620002f857600080fd5b815160ff811681146200030a57600080fd5b9392505050565b600181811c908216806200032657607f821691505b6020821081036200034757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039d576000816000526020600020601f850160051c81016020861015620003785750805b601f850160051c820191505b81811015620003995782815560010162000384565b5050505b505050565b81516001600160401b03811115620003be57620003be62000193565b620003d681620003cf845462000311565b846200034d565b602080601f8311600181146200040e5760008415620003f55750858301515b600019600386901b1c1916600185901b17855562000399565b600085815260208120601f198616915b828110156200043f578886015182559484019460019091019084016200041e565b50858210156200045e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008083546200047e8162000311565b60018281168015620004995760018114620004af57620004e0565b60ff1984168752821515830287019450620004e0565b8760005260208060002060005b85811015620004d75781548a820152908401908201620004bc565b50505082870194505b50929695505050505050565b60805160a05160c05160e051611ca962000542600039600081816102d7015281816110e80152818161119e01528181611373015261154a015260006107f6015260006107c1015260006102960152611ca96000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c80637ecebe001161010f578063c63d75b6116100a2578063d905777e11610071578063d905777e14610470578063dd62ed3e146104a6578063ef8b30f7146104d1578063f8aab906146104e457600080fd5b8063c63d75b61461031e578063c6e6f59214610435578063ce96cb7714610448578063d505accf1461045b57600080fd5b8063a9059cbb116100de578063a9059cbb146103e9578063b3d7f6b9146103fc578063b460af941461040f578063ba0876521461042257600080fd5b80637ecebe00146103a657806394bf804d146103c657806395d89b41146103d957806399530b06146103e157600080fd5b8063313ce567116101875780634cdad506116101565780634cdad506146103515780636a146024146103645780636e553f651461037357806370a082311461038657600080fd5b8063313ce567146102915780633644e515146102ca57806338d52e0f146102d2578063402d267d1461031e57600080fd5b8063095ea7b3116101c3578063095ea7b31461023f5780630a28a4771461026257806318160ddd1461027557806323b872dd1461027e57600080fd5b806301e1d114146101f557806306fdde031461020c578063072200961461022157806307a2d13a1461022c575b600080fd5b6007545b6040519081526020015b60405180910390f35b6102146104ed565b604051610203919061186c565b6101f96305f5e10081565b6101f961023a3660046118d9565b61057b565b61025261024d36600461191b565b6105d0565b6040519015158152602001610203565b6101f96102703660046118d9565b61064a565b6101f960035481565b61025261028c366004611945565b610679565b6102b87f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff9091168152602001610203565b6101f96107bd565b6102f97f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b6101f961032c366004611981565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90565b6101f961035f3660046118d9565b610818565b6101f9670de0b6b3a764000081565b6101f961038136600461199c565b610823565b6101f9610394366004611981565b60046020526000908152604090205481565b6101f96103b4366004611981565b60066020526000908152604090205481565b6101f96103d436600461199c565b6108bb565b61021461095c565b6101f9610969565b6102526103f736600461191b565b61097c565b6101f961040a3660046118d9565b610a01565b6101f961041d3660046119c8565b610a3c565b6101f96104303660046119c8565b610ad1565b6101f96104433660046118d9565b610b73565b6101f9610456366004611981565b610b94565b61046e610469366004611a04565b610bc3565b005b6101f961047e366004611981565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b6101f96104b4366004611a77565b600560209081526000928352604080842090915290825290205481565b6101f96104df3660046118d9565b610ee2565b6101f960075481565b600180546104fa90611aa1565b80601f016020809104026020016040519081016040528092919081815260200182805461052690611aa1565b80156105735780601f1061054857610100808354040283529160200191610573565b820191906000526020600020905b81548152906001019060200180831161055657829003601f168201915b505050505081565b60006305f5e10061058c8184611b23565b6105969190611b5e565b60035490925080156105bb576105b66105ae60075490565b849083610eed565b6105c9565b6105c96305f5e10084611b23565b9392505050565b33600081815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106389086815260200190565b60405180910390a35060015b92915050565b600354600090801561066b576105b68161066360075490565b859190610f29565b6105c96305f5e10084611b5e565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461070d576106db8382611b75565b73ffffffffffffffffffffffffffffffffffffffff861660009081526005602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff851660009081526004602052604081208054859290610742908490611b75565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260046020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107aa9087815260200190565b60405180910390a3506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146107f3576107ee610f6d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b60006106448261057b565b60008054600114610895576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6002600055816108a481611007565b6108ae8484611057565b6001600055949350505050565b60008054600114610928576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e435900000000000000000000000000000000000000000000604482015260640161088c565b60026000558161093781611007565b6305f5e1006109468186611b23565b6109509190611b5e565b93506108ae8484611177565b600280546104fa90611aa1565b60006107ee670de0b6b3a764000061057b565b3360009081526004602052604081208054839190839061099d908490611b75565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260046020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106389086815260200190565b60006305f5e100610a128184611b23565b610a1c9190611b5e565b60035490925080156105bb576105b6610a3460075490565b849083610f29565b60008054600114610aa9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e435900000000000000000000000000000000000000000000604482015260640161088c565b600260005582610ab881611007565b610ac385858561122d565b600160005595945050505050565b60008054600114610b3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e435900000000000000000000000000000000000000000000604482015260640161088c565b600260005582610b4d81611007565b6305f5e100610b5c8187611b23565b610b669190611b5e565b9450610ac385858561139a565b600354600090801561066b576105b681610b8c60075490565b859190610eed565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600460205260408120546106449061057b565b42841015610c2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f45585049524544000000000000000000604482015260640161088c565b60006001610c396107bd565b73ffffffffffffffffffffffffffffffffffffffff8a811660008181526006602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610d8b573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610e0657508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610e6c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e4552000000000000000000000000000000000000604482015260640161088c565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526005602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b600061064482610b73565b6000827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0484118302158202610f2257600080fd5b5091020490565b6000827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0484118302158202610f5e57600080fd5b50910281810615159190040190565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6001604051610f9f9190611b88565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b73ffffffffffffffffffffffffffffffffffffffff8116611054576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b600061106283610ee2565b9050806000036110ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f534841524553000000000000000000000000000000000000000000604482015260640161088c565b61111073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333086611571565b61111a8282611663565b604080518481526020810183905273ffffffffffffffffffffffffffffffffffffffff84169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a361064483826116dc565b600061118283610a01565b90506111c673ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084611571565b6111d08284611663565b604080518281526020810185905273ffffffffffffffffffffffffffffffffffffffff84169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a361064481846116dc565b60006112388461064a565b90503373ffffffffffffffffffffffffffffffffffffffff8316146112ed5773ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146112eb576112b98282611b75565b73ffffffffffffffffffffffffffffffffffffffff841660009081526005602090815260408083203384529091529020555b505b6112f784826116f7565b6113018282611709565b604080518581526020810183905273ffffffffffffffffffffffffffffffffffffffff808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a46105c973ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168486611797565b60003373ffffffffffffffffffffffffffffffffffffffff83161461144f5773ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461144d5761141b8582611b75565b73ffffffffffffffffffffffffffffffffffffffff841660009081526005602090815260408083203384529091529020555b505b61145884610818565b9050806000036114c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f415353455453000000000000000000000000000000000000000000604482015260640161088c565b6114ce81856116f7565b6114d88285611709565b604080518281526020810186905273ffffffffffffffffffffffffffffffffffffffff808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a46105c973ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168483611797565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d116001600051141617169150508061165c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000604482015260640161088c565b5050505050565b80600360008282546116759190611c60565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600460209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a35050565b81600760008282546116ee9190611c60565b90915550505050565b81600760008282546116ee9190611b75565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600460205260408120805483929061173e908490611b75565b909155505060038054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016116d0565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015260640161088c565b50505050565b60006020808352835180602085015260005b8181101561189a5785810183015185820160400152820161187e565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000602082840312156118eb57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461191657600080fd5b919050565b6000806040838503121561192e57600080fd5b611937836118f2565b946020939093013593505050565b60008060006060848603121561195a57600080fd5b611963846118f2565b9250611971602085016118f2565b9150604084013590509250925092565b60006020828403121561199357600080fd5b6105c9826118f2565b600080604083850312156119af57600080fd5b823591506119bf602084016118f2565b90509250929050565b6000806000606084860312156119dd57600080fd5b833592506119ed602085016118f2565b91506119fb604085016118f2565b90509250925092565b600080600080600080600060e0888a031215611a1f57600080fd5b611a28886118f2565b9650611a36602089016118f2565b95506040880135945060608801359350608088013560ff81168114611a5a57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611a8a57600080fd5b611a93836118f2565b91506119bf602084016118f2565b600181811c90821680611ab557607f821691505b602082108103611aee577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082611b59577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761064457610644611af4565b8181038181111561064457610644611af4565b60008083548160018260011c91506001831680611ba657607f831692505b60208084108203611bde577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b818015611bf25760018114611c2557611c52565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952841515850289019650611c52565b60008a81526020902060005b86811015611c4a5781548b820152908501908301611c31565b505084890196505b509498975050505050505050565b8082018082111561064457610644611af456fea2646970667358221220512a52bbbfc747ffafcba3815afd089b73ed565157f84d24e7336463b7d081e564736f6c6343000818003300000000000000000000000018084fba666a33d37592fa2633fd49a74dd93a88000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000075361746f7368690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045341545300000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101f05760003560e01c80637ecebe001161010f578063c63d75b6116100a2578063d905777e11610071578063d905777e14610470578063dd62ed3e146104a6578063ef8b30f7146104d1578063f8aab906146104e457600080fd5b8063c63d75b61461031e578063c6e6f59214610435578063ce96cb7714610448578063d505accf1461045b57600080fd5b8063a9059cbb116100de578063a9059cbb146103e9578063b3d7f6b9146103fc578063b460af941461040f578063ba0876521461042257600080fd5b80637ecebe00146103a657806394bf804d146103c657806395d89b41146103d957806399530b06146103e157600080fd5b8063313ce567116101875780634cdad506116101565780634cdad506146103515780636a146024146103645780636e553f651461037357806370a082311461038657600080fd5b8063313ce567146102915780633644e515146102ca57806338d52e0f146102d2578063402d267d1461031e57600080fd5b8063095ea7b3116101c3578063095ea7b31461023f5780630a28a4771461026257806318160ddd1461027557806323b872dd1461027e57600080fd5b806301e1d114146101f557806306fdde031461020c578063072200961461022157806307a2d13a1461022c575b600080fd5b6007545b6040519081526020015b60405180910390f35b6102146104ed565b604051610203919061186c565b6101f96305f5e10081565b6101f961023a3660046118d9565b61057b565b61025261024d36600461191b565b6105d0565b6040519015158152602001610203565b6101f96102703660046118d9565b61064a565b6101f960035481565b61025261028c366004611945565b610679565b6102b87f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff9091168152602001610203565b6101f96107bd565b6102f97f00000000000000000000000018084fba666a33d37592fa2633fd49a74dd93a8881565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610203565b6101f961032c366004611981565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90565b6101f961035f3660046118d9565b610818565b6101f9670de0b6b3a764000081565b6101f961038136600461199c565b610823565b6101f9610394366004611981565b60046020526000908152604090205481565b6101f96103b4366004611981565b60066020526000908152604090205481565b6101f96103d436600461199c565b6108bb565b61021461095c565b6101f9610969565b6102526103f736600461191b565b61097c565b6101f961040a3660046118d9565b610a01565b6101f961041d3660046119c8565b610a3c565b6101f96104303660046119c8565b610ad1565b6101f96104433660046118d9565b610b73565b6101f9610456366004611981565b610b94565b61046e610469366004611a04565b610bc3565b005b6101f961047e366004611981565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b6101f96104b4366004611a77565b600560209081526000928352604080842090915290825290205481565b6101f96104df3660046118d9565b610ee2565b6101f960075481565b600180546104fa90611aa1565b80601f016020809104026020016040519081016040528092919081815260200182805461052690611aa1565b80156105735780601f1061054857610100808354040283529160200191610573565b820191906000526020600020905b81548152906001019060200180831161055657829003601f168201915b505050505081565b60006305f5e10061058c8184611b23565b6105969190611b5e565b60035490925080156105bb576105b66105ae60075490565b849083610eed565b6105c9565b6105c96305f5e10084611b23565b9392505050565b33600081815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106389086815260200190565b60405180910390a35060015b92915050565b600354600090801561066b576105b68161066360075490565b859190610f29565b6105c96305f5e10084611b5e565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461070d576106db8382611b75565b73ffffffffffffffffffffffffffffffffffffffff861660009081526005602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff851660009081526004602052604081208054859290610742908490611b75565b909155505073ffffffffffffffffffffffffffffffffffffffff808516600081815260046020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107aa9087815260200190565b60405180910390a3506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000146146107f3576107ee610f6d565b905090565b507f784de17dfcac3f86d03c5d65a570b463ec94b4bf0a0d97a08a6fec0c6441317590565b60006106448261057b565b60008054600114610895576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6002600055816108a481611007565b6108ae8484611057565b6001600055949350505050565b60008054600114610928576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e435900000000000000000000000000000000000000000000604482015260640161088c565b60026000558161093781611007565b6305f5e1006109468186611b23565b6109509190611b5e565b93506108ae8484611177565b600280546104fa90611aa1565b60006107ee670de0b6b3a764000061057b565b3360009081526004602052604081208054839190839061099d908490611b75565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600081815260046020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106389086815260200190565b60006305f5e100610a128184611b23565b610a1c9190611b5e565b60035490925080156105bb576105b6610a3460075490565b849083610f29565b60008054600114610aa9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e435900000000000000000000000000000000000000000000604482015260640161088c565b600260005582610ab881611007565b610ac385858561122d565b600160005595945050505050565b60008054600114610b3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e435900000000000000000000000000000000000000000000604482015260640161088c565b600260005582610b4d81611007565b6305f5e100610b5c8187611b23565b610b669190611b5e565b9450610ac385858561139a565b600354600090801561066b576105b681610b8c60075490565b859190610eed565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600460205260408120546106449061057b565b42841015610c2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f45585049524544000000000000000000604482015260640161088c565b60006001610c396107bd565b73ffffffffffffffffffffffffffffffffffffffff8a811660008181526006602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610d8b573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610e0657508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610e6c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e4552000000000000000000000000000000000000604482015260640161088c565b73ffffffffffffffffffffffffffffffffffffffff90811660009081526005602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b600061064482610b73565b6000827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0484118302158202610f2257600080fd5b5091020490565b6000827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0484118302158202610f5e57600080fd5b50910281810615159190040190565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6001604051610f9f9190611b88565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b73ffffffffffffffffffffffffffffffffffffffff8116611054576040517fe6c4247b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b600061106283610ee2565b9050806000036110ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f534841524553000000000000000000000000000000000000000000604482015260640161088c565b61111073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000018084fba666a33d37592fa2633fd49a74dd93a8816333086611571565b61111a8282611663565b604080518481526020810183905273ffffffffffffffffffffffffffffffffffffffff84169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a361064483826116dc565b600061118283610a01565b90506111c673ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000018084fba666a33d37592fa2633fd49a74dd93a8816333084611571565b6111d08284611663565b604080518281526020810185905273ffffffffffffffffffffffffffffffffffffffff84169133917fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7910160405180910390a361064481846116dc565b60006112388461064a565b90503373ffffffffffffffffffffffffffffffffffffffff8316146112ed5773ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146112eb576112b98282611b75565b73ffffffffffffffffffffffffffffffffffffffff841660009081526005602090815260408083203384529091529020555b505b6112f784826116f7565b6113018282611709565b604080518581526020810183905273ffffffffffffffffffffffffffffffffffffffff808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a46105c973ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000018084fba666a33d37592fa2633fd49a74dd93a88168486611797565b60003373ffffffffffffffffffffffffffffffffffffffff83161461144f5773ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461144d5761141b8582611b75565b73ffffffffffffffffffffffffffffffffffffffff841660009081526005602090815260408083203384529091529020555b505b61145884610818565b9050806000036114c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f5a45524f5f415353455453000000000000000000000000000000000000000000604482015260640161088c565b6114ce81856116f7565b6114d88285611709565b604080518281526020810186905273ffffffffffffffffffffffffffffffffffffffff808516929086169133917ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db910160405180910390a46105c973ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000018084fba666a33d37592fa2633fd49a74dd93a88168483611797565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d116001600051141617169150508061165c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000604482015260640161088c565b5050505050565b80600360008282546116759190611c60565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152600460209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a35050565b81600760008282546116ee9190611c60565b90915550505050565b81600760008282546116ee9190611b75565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600460205260408120805483929061173e908490611b75565b909155505060038054829003905560405181815260009073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016116d0565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080611866576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c45440000000000000000000000000000000000604482015260640161088c565b50505050565b60006020808352835180602085015260005b8181101561189a5785810183015185820160400152820161187e565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000602082840312156118eb57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461191657600080fd5b919050565b6000806040838503121561192e57600080fd5b611937836118f2565b946020939093013593505050565b60008060006060848603121561195a57600080fd5b611963846118f2565b9250611971602085016118f2565b9150604084013590509250925092565b60006020828403121561199357600080fd5b6105c9826118f2565b600080604083850312156119af57600080fd5b823591506119bf602084016118f2565b90509250929050565b6000806000606084860312156119dd57600080fd5b833592506119ed602085016118f2565b91506119fb604085016118f2565b90509250925092565b600080600080600080600060e0888a031215611a1f57600080fd5b611a28886118f2565b9650611a36602089016118f2565b95506040880135945060608801359350608088013560ff81168114611a5a57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611a8a57600080fd5b611a93836118f2565b91506119bf602084016118f2565b600181811c90821680611ab557607f821691505b602082108103611aee577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082611b59577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761064457610644611af4565b8181038181111561064457610644611af4565b60008083548160018260011c91506001831680611ba657607f831692505b60208084108203611bde577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b818015611bf25760018114611c2557611c52565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952841515850289019650611c52565b60008a81526020902060005b86811015611c4a5781548b820152908501908301611c31565b505084890196505b509498975050505050505050565b8082018082111561064457610644611af456fea2646970667358221220512a52bbbfc747ffafcba3815afd089b73ed565157f84d24e7336463b7d081e564736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000018084fba666a33d37592fa2633fd49a74dd93a88000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000075361746f7368690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045341545300000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _tBTC (address): 0x18084fbA666a33d37592fA2633fD49a74DD93a88
Arg [1] : _name (string): Satoshi
Arg [2] : _symbol (string): SATS
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 00000000000000000000000018084fba666a33d37592fa2633fd49a74dd93a88
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [4] : 5361746f73686900000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [6] : 5341545300000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.
Add Token to MetaMask (Web3)