编译器
0.8.15+commit.e14f2714
文件 1 的 3:ERC20.sol
pragma solidity >=0.8.0;
abstract contract ERC20 {
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
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;
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];
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
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 {
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)
)
);
}
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}
文件 2 的 3:GMBL.sol
pragma solidity ^0.8.0;
import {ERC20} from "solmate/tokens/ERC20.sol";
import {Kernel, Module, Keycode} from "Default/Kernel.sol";
contract GMBL is ERC20, Module {
error GMBL_Mint_MaxSupplyExceeded();
uint256 public maxSupply;
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_,
uint256 maxSupply_,
Kernel kernel_
) ERC20(name_, symbol_, decimals_) Module(kernel_) {
maxSupply = maxSupply_;
}
function KEYCODE() public pure override returns (Keycode) {
return Keycode.wrap("GMBLE");
}
function mint(address to, uint256 amount) external permissioned {
_mint(to, amount);
}
function burn(uint256 amount) external {
_burn(msg.sender, amount);
}
function _mint(address to, uint256 amount) internal override {
totalSupply += amount;
if (totalSupply > maxSupply) revert GMBL_Mint_MaxSupplyExceeded();
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
}
文件 3 的 3:Kernel.sol
pragma solidity 0.8.15;
enum Actions {
InstallModule,
UpgradeModule,
ActivatePolicy,
DeactivatePolicy,
ChangeExecutor,
MigrateKernel
}
struct Instruction {
Actions action;
address target;
}
struct Permissions {
Keycode keycode;
bytes4 funcSelector;
}
type Keycode is bytes5;
error TargetNotAContract(address target_);
error InvalidKeycode(Keycode keycode_);
function toKeycode(bytes5 keycode_) pure returns (Keycode) {
return Keycode.wrap(keycode_);
}
function fromKeycode(Keycode keycode_) pure returns (bytes5) {
return Keycode.unwrap(keycode_);
}
function ensureContract(address target_) view {
if (target_.code.length == 0) revert TargetNotAContract(target_);
}
function ensureValidKeycode(Keycode keycode_) pure {
bytes5 unwrapped = Keycode.unwrap(keycode_);
for (uint256 i = 0; i < 5; ) {
bytes1 char = unwrapped[i];
if (char < 0x41 || char > 0x5A) revert InvalidKeycode(keycode_);
unchecked {
i++;
}
}
}
abstract contract KernelAdapter {
error KernelAdapter_OnlyKernel(address caller_);
Kernel public kernel;
constructor(Kernel kernel_) {
kernel = kernel_;
}
modifier onlyKernel() {
if (msg.sender != address(kernel)) revert KernelAdapter_OnlyKernel(msg.sender);
_;
}
function changeKernel(Kernel newKernel_) external onlyKernel {
kernel = newKernel_;
}
}
abstract contract Module is KernelAdapter {
error Module_PolicyNotPermitted(address policy_);
constructor(Kernel kernel_) KernelAdapter(kernel_) {}
modifier permissioned() {
if (!kernel.modulePermissions(KEYCODE(), Policy(msg.sender), msg.sig))
revert Module_PolicyNotPermitted(msg.sender);
_;
}
function KEYCODE() public pure virtual returns (Keycode) {}
function VERSION() external pure virtual returns (uint8 major, uint8 minor) {}
function INIT() external virtual onlyKernel {}
}
abstract contract Policy is KernelAdapter {
error Policy_ModuleDoesNotExist(Keycode keycode_);
constructor(Kernel kernel_) KernelAdapter(kernel_) {}
function isActive() external view returns (bool) {
return kernel.isPolicyActive(this);
}
function getModuleAddress(Keycode keycode_) internal view returns (address) {
address moduleForKeycode = address(kernel.getModuleForKeycode(keycode_));
if (moduleForKeycode == address(0)) revert Policy_ModuleDoesNotExist(keycode_);
return moduleForKeycode;
}
function configureDependencies() external virtual returns (Keycode[] memory dependencies) {}
function requestPermissions() external view virtual returns (Permissions[] memory requests) {}
}
contract Kernel {
event PermissionsUpdated(
Keycode indexed keycode_,
Policy indexed policy_,
bytes4 funcSelector_,
bool granted_
);
event ActionExecuted(Actions indexed action_, address indexed target_);
error Kernel_OnlyExecutor(address caller_);
error Kernel_ModuleAlreadyInstalled(Keycode module_);
error Kernel_InvalidModuleUpgrade(Keycode module_);
error Kernel_PolicyAlreadyActivated(address policy_);
error Kernel_PolicyNotActivated(address policy_);
address public executor;
Keycode[] public allKeycodes;
mapping(Keycode => Module) public getModuleForKeycode;
mapping(Module => Keycode) public getKeycodeForModule;
mapping(Keycode => Policy[]) public moduleDependents;
mapping(Keycode => mapping(Policy => uint256)) public getDependentIndex;
mapping(Keycode => mapping(Policy => mapping(bytes4 => bool))) public modulePermissions;
Policy[] public activePolicies;
mapping(Policy => uint256) public getPolicyIndex;
constructor() {
executor = msg.sender;
}
modifier onlyExecutor() {
if (msg.sender != executor) revert Kernel_OnlyExecutor(msg.sender);
_;
}
function isPolicyActive(Policy policy_) public view returns (bool) {
return activePolicies.length > 0 && activePolicies[getPolicyIndex[policy_]] == policy_;
}
function executeAction(Actions action_, address target_) external onlyExecutor {
if (action_ == Actions.InstallModule) {
ensureContract(target_);
ensureValidKeycode(Module(target_).KEYCODE());
_installModule(Module(target_));
} else if (action_ == Actions.UpgradeModule) {
ensureContract(target_);
ensureValidKeycode(Module(target_).KEYCODE());
_upgradeModule(Module(target_));
} else if (action_ == Actions.ActivatePolicy) {
ensureContract(target_);
_activatePolicy(Policy(target_));
} else if (action_ == Actions.DeactivatePolicy) {
ensureContract(target_);
_deactivatePolicy(Policy(target_));
} else if (action_ == Actions.ChangeExecutor) {
executor = target_;
} else if (action_ == Actions.MigrateKernel) {
ensureContract(target_);
_migrateKernel(Kernel(target_));
}
emit ActionExecuted(action_, target_);
}
function _installModule(Module newModule_) internal {
Keycode keycode = newModule_.KEYCODE();
if (address(getModuleForKeycode[keycode]) != address(0))
revert Kernel_ModuleAlreadyInstalled(keycode);
getModuleForKeycode[keycode] = newModule_;
getKeycodeForModule[newModule_] = keycode;
allKeycodes.push(keycode);
newModule_.INIT();
}
function _upgradeModule(Module newModule_) internal {
Keycode keycode = newModule_.KEYCODE();
Module oldModule = getModuleForKeycode[keycode];
if (address(oldModule) == address(0) || oldModule == newModule_)
revert Kernel_InvalidModuleUpgrade(keycode);
getKeycodeForModule[oldModule] = Keycode.wrap(bytes5(0));
getKeycodeForModule[newModule_] = keycode;
getModuleForKeycode[keycode] = newModule_;
newModule_.INIT();
_reconfigurePolicies(keycode);
}
function _activatePolicy(Policy policy_) internal {
if (isPolicyActive(policy_)) revert Kernel_PolicyAlreadyActivated(address(policy_));
activePolicies.push(policy_);
getPolicyIndex[policy_] = activePolicies.length - 1;
Keycode[] memory dependencies = policy_.configureDependencies();
uint256 depLength = dependencies.length;
for (uint256 i; i < depLength; ) {
Keycode keycode = dependencies[i];
moduleDependents[keycode].push(policy_);
getDependentIndex[keycode][policy_] = moduleDependents[keycode].length - 1;
unchecked {
++i;
}
}
Permissions[] memory requests = policy_.requestPermissions();
_setPolicyPermissions(policy_, requests, true);
}
function _deactivatePolicy(Policy policy_) internal {
if (!isPolicyActive(policy_)) revert Kernel_PolicyNotActivated(address(policy_));
Permissions[] memory requests = policy_.requestPermissions();
_setPolicyPermissions(policy_, requests, false);
uint256 idx = getPolicyIndex[policy_];
Policy lastPolicy = activePolicies[activePolicies.length - 1];
activePolicies[idx] = lastPolicy;
activePolicies.pop();
getPolicyIndex[lastPolicy] = idx;
delete getPolicyIndex[policy_];
_pruneFromDependents(policy_);
}
function _migrateKernel(Kernel newKernel_) internal {
uint256 keycodeLen = allKeycodes.length;
for (uint256 i; i < keycodeLen; ) {
Module module = Module(getModuleForKeycode[allKeycodes[i]]);
module.changeKernel(newKernel_);
unchecked {
++i;
}
}
uint256 policiesLen = activePolicies.length;
for (uint256 j; j < policiesLen; ) {
Policy policy = activePolicies[j];
policy.changeKernel(newKernel_);
unchecked {
++j;
}
}
}
function _reconfigurePolicies(Keycode keycode_) internal {
Policy[] memory dependents = moduleDependents[keycode_];
uint256 depLength = dependents.length;
for (uint256 i; i < depLength; ) {
dependents[i].configureDependencies();
unchecked {
++i;
}
}
}
function _setPolicyPermissions(
Policy policy_,
Permissions[] memory requests_,
bool grant_
) internal {
uint256 reqLength = requests_.length;
for (uint256 i = 0; i < reqLength; ) {
Permissions memory request = requests_[i];
modulePermissions[request.keycode][policy_][request.funcSelector] = grant_;
emit PermissionsUpdated(request.keycode, policy_, request.funcSelector, grant_);
unchecked {
++i;
}
}
}
function _pruneFromDependents(Policy policy_) internal {
Keycode[] memory dependencies = policy_.configureDependencies();
uint256 depcLength = dependencies.length;
for (uint256 i; i < depcLength; ) {
Keycode keycode = dependencies[i];
Policy[] storage dependents = moduleDependents[keycode];
uint256 origIndex = getDependentIndex[keycode][policy_];
Policy lastPolicy = dependents[dependents.length - 1];
dependents[origIndex] = lastPolicy;
dependents.pop();
getDependentIndex[keycode][lastPolicy] = origIndex;
delete getDependentIndex[keycode][policy_];
unchecked {
++i;
}
}
}
}
{
"compilationTarget": {
"src/modules/GMBL/GMBL.sol": "GMBL"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1
},
"remappings": [
":Default/=src/Default2/src/",
":ds-test/=lib/ds-test/src/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin-contracts/contracts/",
":prb-test/=lib/Default/lib/prb-test/src/",
":solidity-examples/=lib/solidity-examples/contracts/",
":solmate/=lib/solmate/src/",
":src/=src/",
":test-utils/=lib/Default/lib/test-utils/src/",
":weird-erc20/=lib/Default/lib/solmate/lib/weird-erc20/src/"
]
}
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"uint256","name":"maxSupply_","type":"uint256"},{"internalType":"contract Kernel","name":"kernel_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"GMBL_Mint_MaxSupplyExceeded","type":"error"},{"inputs":[{"internalType":"address","name":"caller_","type":"address"}],"name":"KernelAdapter_OnlyKernel","type":"error"},{"inputs":[{"internalType":"address","name":"policy_","type":"address"}],"name":"Module_PolicyNotPermitted","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":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INIT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"KEYCODE","outputs":[{"internalType":"Keycode","name":"","type":"bytes5"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"uint8","name":"major","type":"uint8"},{"internalType":"uint8","name":"minor","type":"uint8"}],"stateMutability":"pure","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":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Kernel","name":"newKernel_","type":"address"}],"name":"changeKernel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kernel","outputs":[{"internalType":"contract Kernel","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"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"}]