Contract Name:
GamaTokenProxy
Contract Source Code:
File 1 of 1 : GamaTokenProxy
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract GamaTokenProxy {
// EIP-1967 implementation slot
bytes32 private constant IMPLEMENTATION_SLOT =
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
// Custom admin slot
bytes32 private constant ADMIN_SLOT =
keccak256("gama.proxy.admin");
constructor(address logic, address adminAddress, uint256 maxMintable) payable {
require(logic != address(0), "Invalid logic address");
require(adminAddress != address(0), "Invalid admin address");
// Store implementation address
assembly {
sstore(IMPLEMENTATION_SLOT, logic)
}
// Store admin address
bytes32 adminSlot = ADMIN_SLOT;
assembly {
sstore(adminSlot, adminAddress)
}
// Call initialize on logic via delegatecall
bytes memory data = abi.encodeWithSignature("initialize(uint256,address)", maxMintable, adminAddress);
(bool success, bytes memory returndata) = logic.delegatecall(data);
if (!success) {
assembly {
revert(add(returndata, 32), mload(returndata))
}
}
}
function upgradeTo(address newImplementation) external {
require(msg.sender == _admin(), "Only admin can upgrade");
require(newImplementation != address(0), "Invalid implementation");
assembly {
sstore(IMPLEMENTATION_SLOT, newImplementation)
}
}
function implementation() external view returns (address impl) {
assembly {
impl := sload(IMPLEMENTATION_SLOT)
}
}
function getAdmin() external view returns (address adm) {
adm = _admin();
}
function _admin() internal view returns (address adm) {
bytes32 slot = ADMIN_SLOT;
assembly {
adm := sload(slot)
}
}
fallback() external payable {
_delegate();
}
receive() external payable {
_delegate();
}
function _delegate() internal {
address impl;
assembly {
impl := sload(IMPLEMENTATION_SLOT)
}
require(impl != address(0), "No implementation set");
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), impl, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
}