// File contracts/AdminStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
contract AdminStorage {
/**
* @notice Administrator for this contract
*/
address public admin;
/**
* @notice Pending administrator for this contract
*/
address public pendingAdmin;
/**
* @notice Active brains of this contract
*/
address public implementation;
/**
* @notice Pending brains of this contract
*/
address public pendingImplementation;
}
// File contracts/AdminProxy.sol
pragma solidity ^0.8.18;
abstract contract AdminProxy is AdminStorage {
/**
* @notice Emitted when pendingImplementation is changed
*/
event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);
/**
* @notice Emitted when pendingImplementation is accepted, which means implementation is updated
*/
event NewImplementation(address oldImplementation, address newImplementation);
/**
* @notice Emitted when pendingAdmin is changed
*/
event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
/**
* @notice Emitted when pendingAdmin is accepted, which means admin is updated
*/
event NewAdmin(address oldAdmin, address newAdmin);
/**
* @dev Delegates execution to an implementation contract.
* It returns to the external caller whatever the implementation returns
* or forwards reverts.
*/
fallback() external payable {
// delegate all other functions to current implementation
(bool success, ) = implementation.delegatecall(msg.data);
assembly {
let free_mem_ptr := mload(0x40)
let size := returndatasize()
returndatacopy(free_mem_ptr, 0, size)
switch success
case 0 { revert(free_mem_ptr, size) }
default { return(free_mem_ptr, size) }
}
}
/*** Admin Functions ***/
function _setPendingImplementation(address newPendingImplementation) public {
require(msg.sender == admin, "SET_PENDING_IMPLEMENTATION_OWNER_CHECK");
address oldPendingImplementation = pendingImplementation;
pendingImplementation = newPendingImplementation;
emit NewPendingImplementation(oldPendingImplementation, pendingImplementation);
}
/**
* @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation
* @dev Admin function for new implementation to accept it's role as implementation
*/
function _acceptImplementation() public {
// Check caller is pendingImplementation and pendingImplementation ≠ address(0)
require(msg.sender == pendingImplementation && pendingImplementation != address(0),
"ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK");
// Save current values for inclusion in log
address oldImplementation = implementation;
address oldPendingImplementation = pendingImplementation;
implementation = pendingImplementation;
pendingImplementation = address(0);
emit NewImplementation(oldImplementation, implementation);
emit NewPendingImplementation(oldPendingImplementation, pendingImplementation);
}
/**
* @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @param newPendingAdmin New pending admin.
*/
function _setPendingAdmin(address newPendingAdmin) public {
// Check caller = admin
require(msg.sender == admin, "SET_PENDING_ADMIN_OWNER_CHECK");
// Save current value, if any, for inclusion in log
address oldPendingAdmin = pendingAdmin;
// Store pendingAdmin with value newPendingAdmin
pendingAdmin = newPendingAdmin;
// Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)
emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);
}
/**
* @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin
* @dev Admin function for pending admin to accept role and update admin
*/
function _acceptAdmin() public {
// Check caller is pendingAdmin and pendingAdmin ≠ address(0)
require(msg.sender == pendingAdmin && pendingAdmin != address(0), "ACCEPT_ADMIN_PENDING_ADMIN_CHECK");
// Save current values for inclusion in log
address oldAdmin = admin;
address oldPendingAdmin = pendingAdmin;
// Store admin with value pendingAdmin
admin = pendingAdmin;
// Clear the pending value
pendingAdmin = address(0);
emit NewAdmin(oldAdmin, admin);
emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
}
}
// File contracts/StUSDTProxy.sol
pragma solidity ^0.8.18;
contract StUSDTProxy is AdminProxy {
constructor(address _implementation) {
// Set admin to caller
admin = msg.sender;
implementation = _implementation;
}
}
{
"compilationTarget": {
"StUSDTProxy.sol": "StUSDTProxy"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_implementation","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"newImplementation","type":"address"}],"name":"NewImplementation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"NewPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingImplementation","type":"address"}],"name":"NewPendingImplementation","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"_acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_acceptImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"_setPendingAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingImplementation","type":"address"}],"name":"_setPendingImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]