编译器
0.8.15+commit.e14f2714
文件 1 的 11:BytesLib.sol
pragma solidity >=0.8.0 <0.9.0;
library BytesLib {
function concat(
bytes memory _preBytes,
bytes memory _postBytes
)
internal
pure
returns (bytes memory)
{
bytes memory tempBytes;
assembly {
tempBytes := mload(0x40)
let length := mload(_preBytes)
mstore(tempBytes, length)
let mc := add(tempBytes, 0x20)
let end := add(mc, length)
for {
let cc := add(_preBytes, 0x20)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
length := mload(_postBytes)
mstore(tempBytes, add(length, mload(tempBytes)))
mc := end
end := add(mc, length)
for {
let cc := add(_postBytes, 0x20)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(0x40, and(
add(add(end, iszero(add(length, mload(_preBytes)))), 31),
not(31)
))
}
return tempBytes;
}
function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
assembly {
let fslot := sload(_preBytes.slot)
let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
let mlength := mload(_postBytes)
let newlength := add(slength, mlength)
switch add(lt(slength, 32), lt(newlength, 32))
case 2 {
sstore(
_preBytes.slot,
add(
fslot,
add(
mul(
div(
mload(add(_postBytes, 0x20)),
exp(0x100, sub(32, mlength))
),
exp(0x100, sub(32, newlength))
),
mul(mlength, 2)
)
)
)
}
case 1 {
mstore(0x0, _preBytes.slot)
let sc := add(keccak256(0x0, 0x20), div(slength, 32))
sstore(_preBytes.slot, add(mul(newlength, 2), 1))
let submod := sub(32, slength)
let mc := add(_postBytes, submod)
let end := add(_postBytes, mlength)
let mask := sub(exp(0x100, submod), 1)
sstore(
sc,
add(
and(
fslot,
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
),
and(mload(mc), mask)
)
)
for {
mc := add(mc, 0x20)
sc := add(sc, 1)
} lt(mc, end) {
sc := add(sc, 1)
mc := add(mc, 0x20)
} {
sstore(sc, mload(mc))
}
mask := exp(0x100, sub(mc, end))
sstore(sc, mul(div(mload(mc), mask), mask))
}
default {
mstore(0x0, _preBytes.slot)
let sc := add(keccak256(0x0, 0x20), div(slength, 32))
sstore(_preBytes.slot, add(mul(newlength, 2), 1))
let slengthmod := mod(slength, 32)
let mlengthmod := mod(mlength, 32)
let submod := sub(32, slengthmod)
let mc := add(_postBytes, submod)
let end := add(_postBytes, mlength)
let mask := sub(exp(0x100, submod), 1)
sstore(sc, add(sload(sc), and(mload(mc), mask)))
for {
sc := add(sc, 1)
mc := add(mc, 0x20)
} lt(mc, end) {
sc := add(sc, 1)
mc := add(mc, 0x20)
} {
sstore(sc, mload(mc))
}
mask := exp(0x100, sub(mc, end))
sstore(sc, mul(div(mload(mc), mask), mask))
}
}
}
function slice(
bytes memory _bytes,
uint256 _start,
uint256 _length
)
internal
pure
returns (bytes memory)
{
require(_length + 31 >= _length, "slice_overflow");
require(_bytes.length >= _start + _length, "slice_outOfBounds");
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
tempBytes := mload(0x40)
let lengthmod := and(_length, 31)
let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
let end := add(mc, _length)
for {
let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(tempBytes, _length)
mstore(0x40, and(add(mc, 31), not(31)))
}
default {
tempBytes := mload(0x40)
mstore(tempBytes, 0)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
address tempAddress;
assembly {
tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
}
return tempAddress;
}
function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
require(_bytes.length >= _start + 1 , "toUint8_outOfBounds");
uint8 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x1), _start))
}
return tempUint;
}
function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
uint16 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x2), _start))
}
return tempUint;
}
function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
uint32 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x4), _start))
}
return tempUint;
}
function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
uint64 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x8), _start))
}
return tempUint;
}
function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
uint96 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0xc), _start))
}
return tempUint;
}
function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
uint128 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x10), _start))
}
return tempUint;
}
function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
uint256 tempUint;
assembly {
tempUint := mload(add(add(_bytes, 0x20), _start))
}
return tempUint;
}
function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
bytes32 tempBytes32;
assembly {
tempBytes32 := mload(add(add(_bytes, 0x20), _start))
}
return tempBytes32;
}
function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
bool success = true;
assembly {
let length := mload(_preBytes)
switch eq(length, mload(_postBytes))
case 1 {
let cb := 1
let mc := add(_preBytes, 0x20)
let end := add(mc, length)
for {
let cc := add(_postBytes, 0x20)
} eq(add(lt(mc, end), cb), 2) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
if iszero(eq(mload(mc), mload(cc))) {
success := 0
cb := 0
}
}
}
default {
success := 0
}
}
return success;
}
function equalStorage(
bytes storage _preBytes,
bytes memory _postBytes
)
internal
view
returns (bool)
{
bool success = true;
assembly {
let fslot := sload(_preBytes.slot)
let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
let mlength := mload(_postBytes)
switch eq(slength, mlength)
case 1 {
if iszero(iszero(slength)) {
switch lt(slength, 32)
case 1 {
fslot := mul(div(fslot, 0x100), 0x100)
if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
success := 0
}
}
default {
let cb := 1
mstore(0x0, _preBytes.slot)
let sc := keccak256(0x0, 0x20)
let mc := add(_postBytes, 0x20)
let end := add(mc, mlength)
for {} eq(add(lt(mc, end), cb), 2) {
sc := add(sc, 1)
mc := add(mc, 0x20)
} {
if iszero(eq(sload(sc), mload(mc))) {
success := 0
cb := 0
}
}
}
}
}
default {
success := 0
}
}
return success;
}
}
文件 2 的 11:CrossChainBridge.sol
pragma solidity 0.8.15;
import {ERC20} from "solmate/tokens/ERC20.sol";
import {ILayerZeroUserApplicationConfig} from "layer-zero/interfaces/ILayerZeroUserApplicationConfig.sol";
import {ILayerZeroEndpoint} from "layer-zero/interfaces/ILayerZeroEndpoint.sol";
import {ILayerZeroReceiver} from "layer-zero/interfaces/ILayerZeroReceiver.sol";
import {BytesLib} from "layer-zero/util/BytesLib.sol";
import {RolesConsumer} from "modules/ROLES/OlympusRoles.sol";
import {ROLESv1} from "modules/ROLES/ROLES.v1.sol";
import {MINTRv1} from "modules/MINTR/MINTR.v1.sol";
import "src/Kernel.sol";
contract CrossChainBridge is
Policy,
RolesConsumer,
ILayerZeroReceiver,
ILayerZeroUserApplicationConfig
{
using BytesLib for bytes;
error Bridge_InsufficientAmount();
error Bridge_InvalidCaller();
error Bridge_InvalidMessageSource();
error Bridge_NoStoredMessage();
error Bridge_InvalidPayload();
error Bridge_DestinationNotTrusted();
error Bridge_NoTrustedPath();
error Bridge_Deactivated();
error Bridge_TrustedRemoteUninitialized();
event BridgeTransferred(address indexed sender_, uint256 amount_, uint16 indexed dstChain_);
event BridgeReceived(address indexed receiver_, uint256 amount_, uint16 indexed srcChain_);
event MessageFailed(
uint16 srcChainId_,
bytes srcAddress_,
uint64 nonce_,
bytes payload_,
bytes reason_
);
event RetryMessageSuccess(
uint16 srcChainId_,
bytes srcAddress_,
uint64 nonce_,
bytes32 payloadHash_
);
event SetPrecrime(address precrime_);
event SetTrustedRemote(uint16 remoteChainId_, bytes path_);
event SetTrustedRemoteAddress(uint16 remoteChainId_, bytes remoteAddress_);
event SetMinDstGas(uint16 dstChainId_, uint16 type_, uint256 _minDstGas);
event BridgeStatusSet(bool isActive_);
MINTRv1 public MINTR;
ILayerZeroEndpoint public immutable lzEndpoint;
ERC20 public ohm;
bool public bridgeActive;
mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedMessages;
mapping(uint16 => bytes) public trustedRemoteLookup;
address public precrime;
constructor(Kernel kernel_, address endpoint_) Policy(kernel_) {
lzEndpoint = ILayerZeroEndpoint(endpoint_);
bridgeActive = true;
}
function configureDependencies() external override returns (Keycode[] memory dependencies) {
dependencies = new Keycode[](2);
dependencies[0] = toKeycode("MINTR");
dependencies[1] = toKeycode("ROLES");
MINTR = MINTRv1(getModuleAddress(dependencies[0]));
ROLES = ROLESv1(getModuleAddress(dependencies[1]));
ohm = ERC20(address(MINTR.ohm()));
}
function requestPermissions()
external
view
override
returns (Permissions[] memory permissions)
{
Keycode MINTR_KEYCODE = MINTR.KEYCODE();
permissions = new Permissions[](3);
permissions[0] = Permissions(MINTR_KEYCODE, MINTR.mintOhm.selector);
permissions[1] = Permissions(MINTR_KEYCODE, MINTR.burnOhm.selector);
permissions[2] = Permissions(MINTR_KEYCODE, MINTR.increaseMintApproval.selector);
}
function sendOhm(uint16 dstChainId_, address to_, uint256 amount_) external payable {
if (!bridgeActive) revert Bridge_Deactivated();
if (ohm.balanceOf(msg.sender) < amount_) revert Bridge_InsufficientAmount();
bytes memory payload = abi.encode(to_, amount_);
MINTR.burnOhm(msg.sender, amount_);
_sendMessage(dstChainId_, payload, payable(msg.sender), address(0x0), bytes(""), msg.value);
emit BridgeTransferred(msg.sender, amount_, dstChainId_);
}
function _receiveMessage(
uint16 srcChainId_,
bytes memory,
uint64,
bytes memory payload_
) internal {
(address to, uint256 amount) = abi.decode(payload_, (address, uint256));
MINTR.increaseMintApproval(address(this), amount);
MINTR.mintOhm(to, amount);
emit BridgeReceived(to, amount, srcChainId_);
}
function lzReceive(
uint16 srcChainId_,
bytes calldata srcAddress_,
uint64 nonce_,
bytes calldata payload_
) public virtual override {
if (msg.sender != address(lzEndpoint)) revert Bridge_InvalidCaller();
bytes memory trustedRemote = trustedRemoteLookup[srcChainId_];
if (
trustedRemote.length == 0 ||
srcAddress_.length != trustedRemote.length ||
keccak256(srcAddress_) != keccak256(trustedRemote)
) revert Bridge_InvalidMessageSource();
(bool success, bytes memory reason) = address(this).call(
abi.encodeWithSelector(
this.receiveMessage.selector,
srcChainId_,
srcAddress_,
nonce_,
payload_
)
);
if (!success) {
failedMessages[srcChainId_][srcAddress_][nonce_] = keccak256(payload_);
emit MessageFailed(srcChainId_, srcAddress_, nonce_, payload_, reason);
}
}
function receiveMessage(
uint16 srcChainId_,
bytes memory srcAddress_,
uint64 nonce_,
bytes memory payload_
) public {
if (msg.sender != address(this)) revert Bridge_InvalidCaller();
_receiveMessage(srcChainId_, srcAddress_, nonce_, payload_);
}
function retryMessage(
uint16 srcChainId_,
bytes calldata srcAddress_,
uint64 nonce_,
bytes calldata payload_
) public payable virtual {
bytes32 payloadHash = failedMessages[srcChainId_][srcAddress_][nonce_];
if (payloadHash == bytes32(0)) revert Bridge_NoStoredMessage();
if (keccak256(payload_) != payloadHash) revert Bridge_InvalidPayload();
failedMessages[srcChainId_][srcAddress_][nonce_] = bytes32(0);
_receiveMessage(srcChainId_, srcAddress_, nonce_, payload_);
emit RetryMessageSuccess(srcChainId_, srcAddress_, nonce_, payloadHash);
}
function _sendMessage(
uint16 dstChainId_,
bytes memory payload_,
address payable refundAddress_,
address zroPaymentAddress_,
bytes memory adapterParams_,
uint256 nativeFee_
) internal {
bytes memory trustedRemote = trustedRemoteLookup[dstChainId_];
if (trustedRemote.length == 0) revert Bridge_DestinationNotTrusted();
lzEndpoint.send{value: nativeFee_}(
dstChainId_,
trustedRemote,
payload_,
refundAddress_,
zroPaymentAddress_,
adapterParams_
);
}
function estimateSendFee(
uint16 dstChainId_,
address to_,
uint256 amount_,
bytes calldata adapterParams_
) external view returns (uint256 nativeFee, uint256 zroFee) {
bytes memory payload = abi.encode(to_, amount_);
return lzEndpoint.estimateFees(dstChainId_, address(this), payload, false, adapterParams_);
}
function setConfig(
uint16 version_,
uint16 chainId_,
uint256 configType_,
bytes calldata config_
) external override onlyRole("bridge_admin") {
lzEndpoint.setConfig(version_, chainId_, configType_, config_);
}
function setSendVersion(uint16 version_) external override onlyRole("bridge_admin") {
lzEndpoint.setSendVersion(version_);
}
function setReceiveVersion(uint16 version_) external override onlyRole("bridge_admin") {
lzEndpoint.setReceiveVersion(version_);
}
function forceResumeReceive(
uint16 srcChainId_,
bytes calldata srcAddress_
) external override onlyRole("bridge_admin") {
lzEndpoint.forceResumeReceive(srcChainId_, srcAddress_);
}
function setTrustedRemote(
uint16 srcChainId_,
bytes calldata path_
) external onlyRole("bridge_admin") {
trustedRemoteLookup[srcChainId_] = path_;
emit SetTrustedRemote(srcChainId_, path_);
}
function setTrustedRemoteAddress(
uint16 remoteChainId_,
bytes calldata remoteAddress_
) external onlyRole("bridge_admin") {
trustedRemoteLookup[remoteChainId_] = abi.encodePacked(remoteAddress_, address(this));
emit SetTrustedRemoteAddress(remoteChainId_, remoteAddress_);
}
function setPrecrime(address precrime_) external onlyRole("bridge_admin") {
precrime = precrime_;
emit SetPrecrime(precrime_);
}
function setBridgeStatus(bool isActive_) external onlyRole("bridge_admin") {
bridgeActive = isActive_;
emit BridgeStatusSet(isActive_);
}
function getConfig(
uint16 version_,
uint16 chainId_,
address,
uint256 configType_
) external view returns (bytes memory) {
return lzEndpoint.getConfig(version_, chainId_, address(this), configType_);
}
function getTrustedRemoteAddress(uint16 remoteChainId_) external view returns (bytes memory) {
bytes memory path = trustedRemoteLookup[remoteChainId_];
if (path.length == 0) revert Bridge_NoTrustedPath();
return path.slice(0, path.length - 20);
}
function isTrustedRemote(
uint16 srcChainId_,
bytes calldata srcAddress_
) external view returns (bool) {
bytes memory trustedSource = trustedRemoteLookup[srcChainId_];
if (srcAddress_.length == 0 || trustedSource.length == 0)
revert Bridge_TrustedRemoteUninitialized();
return (srcAddress_.length == trustedSource.length &&
keccak256(srcAddress_) == keccak256(trustedSource));
}
}
文件 3 的 11: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);
}
}
文件 4 的 11:ILayerZeroEndpoint.sol
pragma solidity >=0.5.0;
import "./ILayerZeroUserApplicationConfig.sol";
interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;
function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;
function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);
function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);
function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);
function getChainId() external view returns (uint16);
function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;
function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);
function getSendLibraryAddress(address _userApplication) external view returns (address);
function getReceiveLibraryAddress(address _userApplication) external view returns (address);
function isSendingPayload() external view returns (bool);
function isReceivingPayload() external view returns (bool);
function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);
function getSendVersion(address _userApplication) external view returns (uint16);
function getReceiveVersion(address _userApplication) external view returns (uint16);
}
文件 5 的 11:ILayerZeroReceiver.sol
pragma solidity >=0.5.0;
interface ILayerZeroReceiver {
function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;
}
文件 6 的 11:ILayerZeroUserApplicationConfig.sol
pragma solidity >=0.5.0;
interface ILayerZeroUserApplicationConfig {
function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;
function setSendVersion(uint16 _version) external;
function setReceiveVersion(uint16 _version) external;
function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;
}
文件 7 的 11: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 (
msg.sender == address(kernel) ||
!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;
}
}
}
}
文件 8 的 11:MINTR.v1.sol
pragma solidity 0.8.15;
import {OlympusERC20Token as OHM} from "src/external/OlympusERC20.sol";
import "src/Kernel.sol";
abstract contract MINTRv1 is Module {
event IncreaseMintApproval(address indexed policy_, uint256 newAmount_);
event DecreaseMintApproval(address indexed policy_, uint256 newAmount_);
event Mint(address indexed policy_, address indexed to_, uint256 amount_);
event Burn(address indexed policy_, address indexed from_, uint256 amount_);
error MINTR_NotApproved();
error MINTR_ZeroAmount();
error MINTR_NotActive();
OHM public ohm;
bool public active;
mapping(address => uint256) public mintApproval;
modifier onlyWhileActive() {
if (!active) revert MINTR_NotActive();
_;
}
function mintOhm(address to_, uint256 amount_) external virtual;
function burnOhm(address from_, uint256 amount_) external virtual;
function increaseMintApproval(address policy_, uint256 amount_) external virtual;
function decreaseMintApproval(address policy_, uint256 amount_) external virtual;
function deactivate() external virtual;
function activate() external virtual;
}
文件 9 的 11:OlympusERC20.sol
pragma solidity >=0.7.5;
interface IOlympusAuthority {
event GovernorPushed(address indexed from, address indexed to, bool _effectiveImmediately);
event GuardianPushed(address indexed from, address indexed to, bool _effectiveImmediately);
event PolicyPushed(address indexed from, address indexed to, bool _effectiveImmediately);
event VaultPushed(address indexed from, address indexed to, bool _effectiveImmediately);
event GovernorPulled(address indexed from, address indexed to);
event GuardianPulled(address indexed from, address indexed to);
event PolicyPulled(address indexed from, address indexed to);
event VaultPulled(address indexed from, address indexed to);
function governor() external view returns (address);
function guardian() external view returns (address);
function policy() external view returns (address);
function vault() external view returns (address);
}
abstract contract OlympusAccessControlled {
event AuthorityUpdated(IOlympusAuthority indexed authority);
string internal UNAUTHORIZED = "UNAUTHORIZED";
IOlympusAuthority public authority;
constructor(IOlympusAuthority _authority) {
authority = _authority;
emit AuthorityUpdated(_authority);
}
modifier onlyGovernor() {
require(msg.sender == authority.governor(), UNAUTHORIZED);
_;
}
modifier onlyGuardian() {
require(msg.sender == authority.guardian(), UNAUTHORIZED);
_;
}
modifier onlyPermitted() {
require(msg.sender == authority.policy(), UNAUTHORIZED);
_;
}
modifier onlyVault() {
require(msg.sender == authority.vault(), UNAUTHORIZED);
_;
}
function setAuthority(IOlympusAuthority _newAuthority) external onlyGovernor {
authority = _newAuthority;
emit AuthorityUpdated(_newAuthority);
}
}
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return;
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
function tryRecover(bytes32 hash, bytes memory signature)
internal
pure
returns (address, RecoverError)
{
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else if (signature.length == 64) {
bytes32 r;
bytes32 vs;
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s;
uint8 v;
assembly {
s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
v := add(shr(255, vs), 27)
}
return tryRecover(hash, v, r, s);
}
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash)
internal
pure
returns (bytes32)
{
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
abstract contract EIP712 {
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
constructor(string memory name, string memory version) {
uint256 chainID;
assembly {
chainID := chainid()
}
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = chainID;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
_TYPE_HASH = typeHash;
}
function _domainSeparatorV4() internal view returns (bytes32) {
uint256 chainID;
assembly {
chainID := chainid()
}
if (chainID == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
uint256 chainID;
assembly {
chainID := chainid()
}
return keccak256(abi.encode(typeHash, nameHash, versionHash, chainID, address(this)));
}
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
}
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
interface IOHM is IERC20 {
function mint(address account_, uint256 amount_) external;
function burn(uint256 amount) external;
function burnFrom(address account_, uint256 amount_) external;
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
assert(a == b * c + (a % b));
return c;
}
function sqrrt(uint256 a) internal pure returns (uint256 c) {
if (a > 3) {
c = a;
uint256 b = add(div(a, 2), 1);
while (b < c) {
c = b;
b = div(add(div(a, b), b), 2);
}
} else if (a != 0) {
c = 1;
}
}
}
library Counters {
using SafeMath for uint256;
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value.sub(1);
}
}
abstract contract ERC20 is IERC20 {
using SafeMath for uint256;
bytes32 private constant ERC20TOKEN_ERC1820_INTERFACE_ID = keccak256("ERC20Token");
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) internal _allowances;
uint256 internal _totalSupply;
string internal _name;
string internal _symbol;
uint8 internal immutable _decimals;
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_
) {
_name = name_;
_symbol = symbol_;
_decimals = decimals_;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(msg.sender, recipient, amount);
return true;
}
function allowance(address owner, address spender)
public
view
virtual
override
returns (uint256)
{
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(
sender,
msg.sender,
_allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance")
);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue)
public
virtual
returns (bool)
{
_approve(
msg.sender,
spender,
_allowances[msg.sender][spender].sub(
subtractedValue,
"ERC20: decreased allowance below zero"
)
);
return true;
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _beforeTokenTransfer(
address from_,
address to_,
uint256 amount_
) internal virtual {}
}
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
using Counters for Counters.Counter;
mapping(address => Counters.Counter) private _nonces;
bytes32 private immutable _PERMIT_TYPEHASH =
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
);
constructor(string memory name) EIP712(name, "1") {}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override {
require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
bytes32 structHash = keccak256(
abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)
);
bytes32 hash = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(hash, v, r, s);
require(signer == owner, "ERC20Permit: invalid signature");
_approve(owner, spender, value);
}
function nonces(address owner) public view virtual override returns (uint256) {
return _nonces[owner].current();
}
function DOMAIN_SEPARATOR() external view override returns (bytes32) {
return _domainSeparatorV4();
}
function _useNonce(address owner) internal virtual returns (uint256 current) {
Counters.Counter storage nonce = _nonces[owner];
current = nonce.current();
nonce.increment();
}
}
contract OlympusERC20Token is ERC20Permit, IOHM, OlympusAccessControlled {
using SafeMath for uint256;
constructor(address _authority)
ERC20("Olympus", "OHM", 9)
ERC20Permit("Olympus")
OlympusAccessControlled(IOlympusAuthority(_authority))
{}
function mint(address account_, uint256 amount_) external override onlyVault {
_mint(account_, amount_);
}
function burn(uint256 amount) external override {
_burn(msg.sender, amount);
}
function burnFrom(address account_, uint256 amount_) external override {
_burnFrom(account_, amount_);
}
function _burnFrom(address account_, uint256 amount_) internal {
uint256 decreasedAllowance_ = allowance(account_, msg.sender).sub(
amount_,
"ERC20: burn amount exceeds allowance"
);
_approve(account_, msg.sender, decreasedAllowance_);
_burn(account_, amount_);
}
}
文件 10 的 11:OlympusRoles.sol
pragma solidity 0.8.15;
import {ROLESv1} from "src/modules/ROLES/ROLES.v1.sol";
import "src/Kernel.sol";
abstract contract RolesConsumer {
ROLESv1 public ROLES;
modifier onlyRole(bytes32 role_) {
ROLES.requireRole(role_, msg.sender);
_;
}
}
contract OlympusRoles is ROLESv1 {
constructor(Kernel kernel_) Module(kernel_) {}
function KEYCODE() public pure override returns (Keycode) {
return toKeycode("ROLES");
}
function VERSION() external pure override returns (uint8 major, uint8 minor) {
major = 1;
minor = 0;
}
function saveRole(bytes32 role_, address addr_) external override permissioned {
if (hasRole[addr_][role_]) revert ROLES_AddressAlreadyHasRole(addr_, role_);
ensureValidRole(role_);
hasRole[addr_][role_] = true;
emit RoleGranted(role_, addr_);
}
function removeRole(bytes32 role_, address addr_) external override permissioned {
if (!hasRole[addr_][role_]) revert ROLES_AddressDoesNotHaveRole(addr_, role_);
hasRole[addr_][role_] = false;
emit RoleRevoked(role_, addr_);
}
function requireRole(bytes32 role_, address caller_) external view override {
if (!hasRole[caller_][role_]) revert ROLES_RequireRole(role_);
}
function ensureValidRole(bytes32 role_) public pure override {
for (uint256 i = 0; i < 32; ) {
bytes1 char = role_[i];
if ((char < 0x61 || char > 0x7A) && char != 0x5f && char != 0x00) {
revert ROLES_InvalidRole(role_);
}
unchecked {
i++;
}
}
}
}
文件 11 的 11:ROLES.v1.sol
pragma solidity 0.8.15;
import "src/Kernel.sol";
abstract contract ROLESv1 is Module {
event RoleGranted(bytes32 indexed role_, address indexed addr_);
event RoleRevoked(bytes32 indexed role_, address indexed addr_);
error ROLES_InvalidRole(bytes32 role_);
error ROLES_RequireRole(bytes32 role_);
error ROLES_AddressAlreadyHasRole(address addr_, bytes32 role_);
error ROLES_AddressDoesNotHaveRole(address addr_, bytes32 role_);
error ROLES_RoleDoesNotExist(bytes32 role_);
mapping(address => mapping(bytes32 => bool)) public hasRole;
function saveRole(bytes32 role_, address addr_) external virtual;
function removeRole(bytes32 role_, address addr_) external virtual;
function requireRole(bytes32 role_, address caller_) external virtual;
function ensureValidRole(bytes32 role_) external pure virtual;
}
{
"compilationTarget": {
"src/policies/CrossChainBridge.sol": "CrossChainBridge"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 10
},
"remappings": [
":@openzeppelin/=lib/openzeppelin-contracts/",
":balancer-v2/=lib/balancer-v2/",
":bonds/=lib/bonds/src/",
":ds-test/=lib/ds-test/src/",
":forge-std/=lib/forge-std/src/",
":interfaces/=src/interfaces/",
":layer-zero/=lib/solidity-examples/contracts/",
":libraries/=src/libraries/",
":modules/=src/modules/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":policies/=src/policies/",
":solidity-examples/=lib/solidity-examples/contracts/",
":solmate/=lib/solmate/src/",
":test/=src/test/"
]
}
[{"inputs":[{"internalType":"contract Kernel","name":"kernel_","type":"address"},{"internalType":"address","name":"endpoint_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Bridge_Deactivated","type":"error"},{"inputs":[],"name":"Bridge_DestinationNotTrusted","type":"error"},{"inputs":[],"name":"Bridge_InsufficientAmount","type":"error"},{"inputs":[],"name":"Bridge_InvalidCaller","type":"error"},{"inputs":[],"name":"Bridge_InvalidMessageSource","type":"error"},{"inputs":[],"name":"Bridge_InvalidPayload","type":"error"},{"inputs":[],"name":"Bridge_NoStoredMessage","type":"error"},{"inputs":[],"name":"Bridge_NoTrustedPath","type":"error"},{"inputs":[],"name":"Bridge_TrustedRemoteUninitialized","type":"error"},{"inputs":[{"internalType":"address","name":"caller_","type":"address"}],"name":"KernelAdapter_OnlyKernel","type":"error"},{"inputs":[{"internalType":"Keycode","name":"keycode_","type":"bytes5"}],"name":"Policy_ModuleDoesNotExist","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver_","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"},{"indexed":true,"internalType":"uint16","name":"srcChain_","type":"uint16"}],"name":"BridgeReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isActive_","type":"bool"}],"name":"BridgeStatusSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender_","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount_","type":"uint256"},{"indexed":true,"internalType":"uint16","name":"dstChain_","type":"uint16"}],"name":"BridgeTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"srcAddress_","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"nonce_","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"payload_","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"reason_","type":"bytes"}],"name":"MessageFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"srcAddress_","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"nonce_","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"payloadHash_","type":"bytes32"}],"name":"RetryMessageSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"dstChainId_","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"type_","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"_minDstGas","type":"uint256"}],"name":"SetMinDstGas","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"precrime_","type":"address"}],"name":"SetPrecrime","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"remoteChainId_","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"path_","type":"bytes"}],"name":"SetTrustedRemote","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"remoteChainId_","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"remoteAddress_","type":"bytes"}],"name":"SetTrustedRemoteAddress","type":"event"},{"inputs":[],"name":"MINTR","outputs":[{"internalType":"contract MINTRv1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLES","outputs":[{"internalType":"contract ROLESv1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract Kernel","name":"newKernel_","type":"address"}],"name":"changeKernel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"configureDependencies","outputs":[{"internalType":"Keycode[]","name":"dependencies","type":"bytes5[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"dstChainId_","type":"uint16"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"bytes","name":"adapterParams_","type":"bytes"}],"name":"estimateSendFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"zroFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"failedMessages","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"internalType":"bytes","name":"srcAddress_","type":"bytes"}],"name":"forceResumeReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"version_","type":"uint16"},{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"configType_","type":"uint256"}],"name":"getConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"remoteChainId_","type":"uint16"}],"name":"getTrustedRemoteAddress","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"internalType":"bytes","name":"srcAddress_","type":"bytes"}],"name":"isTrustedRemote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kernel","outputs":[{"internalType":"contract Kernel","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lzEndpoint","outputs":[{"internalType":"contract ILayerZeroEndpoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"internalType":"bytes","name":"srcAddress_","type":"bytes"},{"internalType":"uint64","name":"nonce_","type":"uint64"},{"internalType":"bytes","name":"payload_","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ohm","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"precrime","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"internalType":"bytes","name":"srcAddress_","type":"bytes"},{"internalType":"uint64","name":"nonce_","type":"uint64"},{"internalType":"bytes","name":"payload_","type":"bytes"}],"name":"receiveMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestPermissions","outputs":[{"components":[{"internalType":"Keycode","name":"keycode","type":"bytes5"},{"internalType":"bytes4","name":"funcSelector","type":"bytes4"}],"internalType":"struct Permissions[]","name":"permissions","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"internalType":"bytes","name":"srcAddress_","type":"bytes"},{"internalType":"uint64","name":"nonce_","type":"uint64"},{"internalType":"bytes","name":"payload_","type":"bytes"}],"name":"retryMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"dstChainId_","type":"uint16"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"sendOhm","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"isActive_","type":"bool"}],"name":"setBridgeStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"version_","type":"uint16"},{"internalType":"uint16","name":"chainId_","type":"uint16"},{"internalType":"uint256","name":"configType_","type":"uint256"},{"internalType":"bytes","name":"config_","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"precrime_","type":"address"}],"name":"setPrecrime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"version_","type":"uint16"}],"name":"setReceiveVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"version_","type":"uint16"}],"name":"setSendVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"srcChainId_","type":"uint16"},{"internalType":"bytes","name":"path_","type":"bytes"}],"name":"setTrustedRemote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"remoteChainId_","type":"uint16"},{"internalType":"bytes","name":"remoteAddress_","type":"bytes"}],"name":"setTrustedRemoteAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"trustedRemoteLookup","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"}]