ETH Price: $3,669.66 (-0.93%)

Contract

0x8b3EFBEfa6eD222077455d6f0DCdA3bF4f3F57A6

Overview

ETH Balance

0 ETH

ETH Value

$0.00
Transaction Hash
Method
Block
From
To
0x3461004e66033982023-10-25 13:49:18403 days ago1698241758IN
 Create: ProxyAdmin
0 ETH0.000510531.43

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ProxyAdmin

Compiler Version
vyper:0.3.10

Optimization Enabled:
N/A

Other Settings:
MIT license

Contract Source Code (Vyper language format)

# pragma version 0.3.10
# pragma evm-version paris
"""
@title ProxyAdmin
@notice Thin proxy allowing shared ownership of contracts
@author Ben Hauser
@license MIT
"""


event TransactionExecuted:
    admin: indexed(address)
    target: indexed(address)
    calldata: Bytes[100000]
    value: uint256

event RequestAdminChange:
    current_admin: address
    future_admin: address

event RevokeAdminChange:
    current_admin: address
    future_admin: address
    calling_admin: address

event ApproveAdminChange:
    current_admin: address
    future_admin: address
    calling_admin: address

event AcceptAdminChange:
    previous_admin: address
    current_admin: address


admins: public(address[2])

pending_current_admin: uint256
pending_new_admin: address
change_approved: bool


@external
def __init__(_authorized: address[2]):
    """
    @notice Contract constructor
    @param _authorized Admin accounts for this contract
    """
    self.admins = _authorized


@payable
@external
def execute(_target: address, _calldata: Bytes[100000]):
    """
    @notice Execute a contract call
    @dev Ether sent when calling this function is forwarded onward
    @param _target Address of the contract to call
    @param _calldata Calldata to use in the call
    """
    assert msg.sender in self.admins  # dev: only admin

    raw_call(_target, _calldata, value=msg.value)
    log TransactionExecuted(msg.sender, _target, _calldata, msg.value)


@view
@external
def get_admin_change_status() -> (address, address, bool):
    """
    @notice Get information about a pending admin change
    @return Admin address to be replaced,
            admin address to be added,
            has change been approved?
    """
    idx: uint256 = self.pending_current_admin
    if idx == 0:
        return ZERO_ADDRESS, ZERO_ADDRESS, False
    else:
        return self.admins[idx - 1], self.pending_new_admin, self.change_approved


@external
def request_admin_change(_new_admin: address):
    """
    @notice Initiate changing an admin address
    @param _new_admin New admin address (replaces msg.sender)
    """
    assert self.pending_current_admin == 0  # dev: already an active request

    admin_list: address[2] = self.admins
    assert _new_admin not in admin_list  # dev: new admin is already admin

    for i in range(2):
        if admin_list[i] == msg.sender:
            self.pending_current_admin = i + 1
            self.pending_new_admin = _new_admin
            log RequestAdminChange(msg.sender, _new_admin)
            return

    raise  # dev: only admin


@external
def approve_admin_change():
    """
    @notice Approve changing an admin address
    @dev Only callable by the 2nd admin address (the one that will not change)
    """
    idx: uint256 = self.pending_current_admin

    assert idx > 0  # dev: no active request
    assert msg.sender == self.admins[idx % 2]  # dev: caller is not 2nd admin

    self.change_approved = True
    log ApproveAdminChange(self.admins[idx - 1], self.pending_new_admin, msg.sender)


@external
def revoke_admin_change():
    """
    @notice Revoke changing an admin address
    @dev May be called by either admin at any time to reset the process,
         even if approval has previous been given
    """
    assert msg.sender in self.admins  # dev: only admin

    idx: uint256 = self.pending_current_admin
    pending_admin: address = ZERO_ADDRESS
    if idx > 0:
        pending_admin = self.admins[idx - 1]

    log RevokeAdminChange(pending_admin, self.pending_new_admin, msg.sender)

    self.pending_current_admin = 0
    self.pending_new_admin = ZERO_ADDRESS
    self.change_approved = False



@external
def accept_admin_change():
    """
    @notice Accept a changed admin address
    @dev Only callable by the new admin address, after approval has been given
    """
    assert self.change_approved == True  # dev: change not approved
    assert msg.sender == self.pending_new_admin  # dev: only new admin

    idx: uint256 = self.pending_current_admin - 1
    log AcceptAdminChange(self.admins[idx], msg.sender)
    self.admins[idx] = msg.sender

    self.pending_current_admin = 0
    self.pending_new_admin = ZERO_ADDRESS
    self.change_approved = False

Contract Security Audit

Contract ABI

[{"name":"TransactionExecuted","inputs":[{"name":"admin","type":"address","indexed":true},{"name":"target","type":"address","indexed":true},{"name":"calldata","type":"bytes","indexed":false},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RequestAdminChange","inputs":[{"name":"current_admin","type":"address","indexed":false},{"name":"future_admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"RevokeAdminChange","inputs":[{"name":"current_admin","type":"address","indexed":false},{"name":"future_admin","type":"address","indexed":false},{"name":"calling_admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"ApproveAdminChange","inputs":[{"name":"current_admin","type":"address","indexed":false},{"name":"future_admin","type":"address","indexed":false},{"name":"calling_admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"AcceptAdminChange","inputs":[{"name":"previous_admin","type":"address","indexed":false},{"name":"current_admin","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_authorized","type":"address[2]"}],"outputs":[]},{"stateMutability":"payable","type":"function","name":"execute","inputs":[{"name":"_target","type":"address"},{"name":"_calldata","type":"bytes"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"get_admin_change_status","inputs":[],"outputs":[{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"request_admin_change","inputs":[{"name":"_new_admin","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"approve_admin_change","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"revoke_admin_change","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"accept_admin_change","inputs":[],"outputs":[]},{"stateMutability":"view","type":"function","name":"admins","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"address"}]}]

3461004e5760206105106000396000518060a01c61004e5760405260206105306000396000518060a01c61004e576060526040516000556060516001556104a9610053610000396104a9610000f35b600080fd60003560e01c60026006820660011b61049d01601e39600051565b6314bfd6d08118610044576024361034176104985760043560018111610498575460405260206040f35b63980cbc14811861049257346104985760016004541861049857600354331861049857600254600181038181116104985790506040527f3f26d618a9f0bbc232d4e0814ca8f1b77fec61eff610a967d549270accd437fc6040516001811161049857546060523360805260406060a13360405160018111610498575560006002556000600355600060045500610492565b631cff79cd8118610492576063361115610498576004358060a01c61049857604052602435600401620186a081351161049857602081350180826060375050336000620187205260006002905b805483186101365760016201872052610141565b600101818118610122575b50506201872051905015610498576040515a606050600060006060516080348686f190509050610176573d600060003e3d6000fd5b604051337fcaac11c45e5fdb5c513e20ac229a3f9f99143580b5eb08d0fecbdd5ae8c81ef56040806201872052806201872001602060605101808282606060045afa50508051806020830101601f82600003163682375050601f19601f8251602001011690508101905034620187405262018720a300610492565b6364bcd7308118610250573461049857600254604052604051610221576060366060376060606061024e5661024e565b6040516001810381811161049857905060018111610498575460605260035460805260045460a052606060605bf35b63d1266a128118610492573461049857600254604052604051156104985760405160018116905060018111610498575433186104985760016004557fb4a2afe1602258539e7638f32a9c55473646a5b004d1a2f76ed802bdd6b3c611604051600181038181116104985790506001811161049857546060526003546080523360a05260606060a100610492565b63a52e736981186103d657602436103417610498576004358060a01c6104985760405260025461049857600054606052600154608052604051600160a05260006002905b8060051b60600151831861033957600060a052610344565b600101818118610321575b505060a0519050156104985760006002905b8060a0523360a051600181116104985760051b60600151186103c25760a051600181018181106104985790506002556040516003557f3dbc538770ecfcda0a15ac4731d922045333e3f55a9dbff4923d5ae950fd4b683360c05260405160e052604060c0a150506103d4565b60010181811861035657505060006000fd5b005b631d43f539811861049257346104985733600060405260006002905b8054831861040457600160405261040f565b6001018181186103f2575b50506040519050156104985760025460405260006060526040511561044b57604051600181038181116104985790506001811161049857546060525b7f65d4d3bd6f71ee062f64e7b4a0b8f2a379c599a6844765e697f102360580029660605160805260035460a0523360c05260606080a1600060025560006003556000600455005b60006000fd5b600080fd001a049201f100d5049202dd841904a9810c00a16576797065728300030a00140000000000000000000000002d12d0907a388811e3aa855a550f959501d303ee000000000000000000000000babe61887f1de2713c6f97e567623453d3c79f67

Deployed Bytecode

0x60003560e01c60026006820660011b61049d01601e39600051565b6314bfd6d08118610044576024361034176104985760043560018111610498575460405260206040f35b63980cbc14811861049257346104985760016004541861049857600354331861049857600254600181038181116104985790506040527f3f26d618a9f0bbc232d4e0814ca8f1b77fec61eff610a967d549270accd437fc6040516001811161049857546060523360805260406060a13360405160018111610498575560006002556000600355600060045500610492565b631cff79cd8118610492576063361115610498576004358060a01c61049857604052602435600401620186a081351161049857602081350180826060375050336000620187205260006002905b805483186101365760016201872052610141565b600101818118610122575b50506201872051905015610498576040515a606050600060006060516080348686f190509050610176573d600060003e3d6000fd5b604051337fcaac11c45e5fdb5c513e20ac229a3f9f99143580b5eb08d0fecbdd5ae8c81ef56040806201872052806201872001602060605101808282606060045afa50508051806020830101601f82600003163682375050601f19601f8251602001011690508101905034620187405262018720a300610492565b6364bcd7308118610250573461049857600254604052604051610221576060366060376060606061024e5661024e565b6040516001810381811161049857905060018111610498575460605260035460805260045460a052606060605bf35b63d1266a128118610492573461049857600254604052604051156104985760405160018116905060018111610498575433186104985760016004557fb4a2afe1602258539e7638f32a9c55473646a5b004d1a2f76ed802bdd6b3c611604051600181038181116104985790506001811161049857546060526003546080523360a05260606060a100610492565b63a52e736981186103d657602436103417610498576004358060a01c6104985760405260025461049857600054606052600154608052604051600160a05260006002905b8060051b60600151831861033957600060a052610344565b600101818118610321575b505060a0519050156104985760006002905b8060a0523360a051600181116104985760051b60600151186103c25760a051600181018181106104985790506002556040516003557f3dbc538770ecfcda0a15ac4731d922045333e3f55a9dbff4923d5ae950fd4b683360c05260405160e052604060c0a150506103d4565b60010181811861035657505060006000fd5b005b631d43f539811861049257346104985733600060405260006002905b8054831861040457600160405261040f565b6001018181186103f2575b50506040519050156104985760025460405260006060526040511561044b57604051600181038181116104985790506001811161049857546060525b7f65d4d3bd6f71ee062f64e7b4a0b8f2a379c599a6844765e697f102360580029660605160805260035460a0523360c05260606080a1600060025560006003556000600455005b60006000fd5b600080fd001a049201f100d5049202dd

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000002d12d0907a388811e3aa855a550f959501d303ee000000000000000000000000babe61887f1de2713c6f97e567623453d3c79f67

-----Decoded View---------------
Arg [0] : _authorized (address[2]): 0x2d12D0907A388811e3AA855A550F959501d303EE,0xbabe61887f1de2713c6f97e567623453d3C79f67

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000002d12d0907a388811e3aa855a550f959501d303ee
Arg [1] : 000000000000000000000000babe61887f1de2713c6f97e567623453d3c79f67


Block Transaction Gas Used Reward
view all blocks sequenced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.