文件 1 的 11:IDefaultImplementationBeacon.sol
pragma solidity ^0.8.7;
interface IDefaultImplementationBeacon {
function defaultImplementation() external view returns (address defaultImplementation_);
}
文件 2 的 11:IMapleLoanFactory.sol
pragma solidity 0.8.7;
import { IMapleProxyFactory } from "../../modules/maple-proxy-factory/contracts/interfaces/IMapleProxyFactory.sol";
interface IMapleLoanFactory is IMapleProxyFactory {
function isLoan(address proxy_) external view returns (bool isLoan_);
}
文件 3 的 11:IMapleProxied.sol
pragma solidity 0.8.7;
import { IProxied } from "../../modules/proxy-factory/contracts/interfaces/IProxied.sol";
interface IMapleProxied is IProxied {
event Upgraded(uint256 toVersion_, bytes arguments_);
function upgrade(uint256 toVersion_, bytes calldata arguments_) external;
}
文件 4 的 11:IMapleProxyFactory.sol
pragma solidity 0.8.7;
import { IDefaultImplementationBeacon } from "../../modules/proxy-factory/contracts/interfaces/IDefaultImplementationBeacon.sol";
interface IMapleProxyFactory is IDefaultImplementationBeacon {
event DefaultVersionSet(uint256 indexed version_);
event ImplementationRegistered(uint256 indexed version_, address indexed implementationAddress_, address indexed initializer_);
event InstanceDeployed(uint256 indexed version_, address indexed instance_, bytes initializationArguments_);
event InstanceUpgraded(address indexed instance_, uint256 indexed fromVersion_, uint256 indexed toVersion_, bytes migrationArguments_);
event MapleGlobalsSet(address indexed mapleGlobals_);
event UpgradePathDisabled(uint256 indexed fromVersion_, uint256 indexed toVersion_);
event UpgradePathEnabled(uint256 indexed fromVersion_, uint256 indexed toVersion_, address indexed migrator_);
function defaultVersion() external view returns (uint256 defaultVersion_);
function mapleGlobals() external view returns (address mapleGlobals_);
function upgradeEnabledForPath(uint256 toVersion_, uint256 fromVersion_) external view returns (bool allowed_);
function createInstance(bytes calldata arguments_, bytes32 salt_) external returns (address instance_);
function enableUpgradePath(uint256 fromVersion_, uint256 toVersion_, address migrator_) external;
function disableUpgradePath(uint256 fromVersion_, uint256 toVersion_) external;
function registerImplementation(uint256 version_, address implementationAddress_, address initializer_) external;
function setDefaultVersion(uint256 version_) external;
function setGlobals(address mapleGlobals_) external;
function upgradeInstance(uint256 toVersion_, bytes calldata arguments_) external;
function getInstanceAddress(bytes calldata arguments_, bytes32 salt_) external view returns (address instanceAddress_);
function implementationOf(uint256 version_) external view returns (address implementation_);
function isInstance(address instance_) external view returns (bool isInstance_);
function migratorForPath(uint256 oldVersion_, uint256 newVersion_) external view returns (address migrator_);
function versionOf(address implementation_) external view returns (uint256 version_);
}
文件 5 的 11:IProxied.sol
pragma solidity ^0.8.7;
interface IProxied {
function factory() external view returns (address factory_);
function implementation() external view returns (address implementation_);
function setImplementation(address newImplementation_) external;
function migrate(address migrator_, bytes calldata arguments_) external;
}
文件 6 的 11:Interfaces.sol
pragma solidity 0.8.7;
interface IGlobalsLike {
function canDeploy(address caller_) external view returns (bool canDeploy_);
function governor() external view returns (address governor_);
function isBorrower(address account_) external view returns (bool isBorrower_);
function isFunctionPaused(bytes4 sig_) external view returns (bool isFunctionPaused_);
function isInstanceOf(bytes32 instanceId_, address instance_) external view returns (bool isInstance_);
function isPoolAsset(address poolAsset_) external view returns (bool isPoolAsset_);
function platformServiceFeeRate(address poolManager) external view returns (uint256 platformServiceFeeRate_);
function securityAdmin() external view returns (address securityAdmin_);
}
interface ILenderLike {
function claim(
int256 principal_,
uint256 interest_,
uint256 delegateServiceFee_,
uint256 platformServiceFee_,
uint40 paymentDueDate_
) external;
function factory() external view returns (address factory_);
function fundsAsset() external view returns (address fundsAsset_);
function poolManager() external view returns (address poolManager_);
}
interface IMapleProxyFactoryLike {
function isInstance(address instance_) external view returns (bool isInstance_);
function mapleGlobals() external view returns (address mapleGlobals_);
}
文件 7 的 11:MapleLoanFactory.sol
pragma solidity 0.8.7;
import { IMapleProxyFactory, MapleProxyFactory } from "../modules/maple-proxy-factory/contracts/MapleProxyFactory.sol";
import { IMapleLoanFactory } from "./interfaces/IMapleLoanFactory.sol";
import { IGlobalsLike } from "./interfaces/Interfaces.sol";
contract MapleLoanFactory is IMapleLoanFactory, MapleProxyFactory {
mapping(address => bool) public override isLoan;
constructor(address mapleGlobals_) MapleProxyFactory(mapleGlobals_) {}
function createInstance(bytes calldata arguments_, bytes32 salt_)
override(IMapleProxyFactory, MapleProxyFactory) public returns (
address instance_
)
{
require(IGlobalsLike(mapleGlobals).canDeploy(msg.sender), "LF:CI:CANNOT_DEPLOY");
isLoan[instance_ = super.createInstance(arguments_, salt_)] = true;
}
}
文件 8 的 11:MapleProxyFactory.sol
pragma solidity 0.8.7;
import { ProxyFactory } from "../modules/proxy-factory/contracts/ProxyFactory.sol";
import { IMapleGlobalsLike } from "./interfaces/Interfaces.sol";
import { IMapleProxied } from "./interfaces/IMapleProxied.sol";
import { IMapleProxyFactory } from "./interfaces/IMapleProxyFactory.sol";
contract MapleProxyFactory is IMapleProxyFactory, ProxyFactory {
address public override mapleGlobals;
uint256 public override defaultVersion;
mapping(address => bool) public override isInstance;
mapping(uint256 => mapping(uint256 => bool)) public override upgradeEnabledForPath;
constructor(address mapleGlobals_) {
require(IMapleGlobalsLike(mapleGlobals = mapleGlobals_).governor() != address(0), "MPF:C:INVALID_GLOBALS");
}
modifier onlyGovernor() {
require(msg.sender == IMapleGlobalsLike(mapleGlobals).governor(), "MPF:NOT_GOVERNOR");
_;
}
modifier whenProtocolNotPaused() {
require(!IMapleGlobalsLike(mapleGlobals).protocolPaused(), "MPF:PROTOCOL_PAUSED");
_;
}
function disableUpgradePath(uint256 fromVersion_, uint256 toVersion_) public override virtual onlyGovernor {
require(fromVersion_ != toVersion_, "MPF:DUP:OVERWRITING_INITIALIZER");
require(_registerMigrator(fromVersion_, toVersion_, address(0)), "MPF:DUP:FAILED");
emit UpgradePathDisabled(fromVersion_, toVersion_);
upgradeEnabledForPath[fromVersion_][toVersion_] = false;
}
function enableUpgradePath(uint256 fromVersion_, uint256 toVersion_, address migrator_) public override virtual onlyGovernor {
require(fromVersion_ != toVersion_, "MPF:EUP:OVERWRITING_INITIALIZER");
require(_registerMigrator(fromVersion_, toVersion_, migrator_), "MPF:EUP:FAILED");
emit UpgradePathEnabled(fromVersion_, toVersion_, migrator_);
upgradeEnabledForPath[fromVersion_][toVersion_] = true;
}
function registerImplementation(uint256 version_, address implementationAddress_, address initializer_)
public override virtual onlyGovernor
{
require(version_ != uint256(0), "MPF:RI:INVALID_VERSION");
emit ImplementationRegistered(version_, implementationAddress_, initializer_);
require(_registerImplementation(version_, implementationAddress_), "MPF:RI:FAIL_FOR_IMPLEMENTATION");
require(_registerMigrator(version_, version_, initializer_), "MPF:RI:FAIL_FOR_MIGRATOR");
}
function setDefaultVersion(uint256 version_) public override virtual onlyGovernor {
require(version_ == 0 || _implementationOf[version_] != address(0), "MPF:SDV:INVALID_VERSION");
emit DefaultVersionSet(defaultVersion = version_);
}
function setGlobals(address mapleGlobals_) public override virtual onlyGovernor {
require(IMapleGlobalsLike(mapleGlobals_).governor() != address(0), "MPF:SG:INVALID_GLOBALS");
emit MapleGlobalsSet(mapleGlobals = mapleGlobals_);
}
function createInstance(bytes calldata arguments_, bytes32 salt_)
public override virtual whenProtocolNotPaused returns (address instance_)
{
bool success;
( success, instance_ ) = _newInstance(arguments_, keccak256(abi.encodePacked(arguments_, salt_)));
require(success, "MPF:CI:FAILED");
isInstance[instance_] = true;
emit InstanceDeployed(defaultVersion, instance_, arguments_);
}
function upgradeInstance(uint256 toVersion_, bytes calldata arguments_) public override virtual whenProtocolNotPaused {
uint256 fromVersion = _versionOf[IMapleProxied(msg.sender).implementation()];
require(upgradeEnabledForPath[fromVersion][toVersion_], "MPF:UI:NOT_ALLOWED");
emit InstanceUpgraded(msg.sender, fromVersion, toVersion_, arguments_);
require(_upgradeInstance(msg.sender, toVersion_, arguments_), "MPF:UI:FAILED");
}
function getInstanceAddress(bytes calldata arguments_, bytes32 salt_) public view override virtual returns (address instanceAddress_) {
return _getDeterministicProxyAddress(keccak256(abi.encodePacked(arguments_, salt_)));
}
function implementationOf(uint256 version_) public view override virtual returns (address implementation_) {
return _implementationOf[version_];
}
function defaultImplementation() external view override returns (address defaultImplementation_) {
return _implementationOf[defaultVersion];
}
function migratorForPath(uint256 oldVersion_, uint256 newVersion_) public view override virtual returns (address migrator_) {
return _migratorForPath[oldVersion_][newVersion_];
}
function versionOf(address implementation_) public view override virtual returns (uint256 version_) {
return _versionOf[implementation_];
}
}
文件 9 的 11:Proxy.sol
pragma solidity ^0.8.7;
import { IDefaultImplementationBeacon } from "./interfaces/IDefaultImplementationBeacon.sol";
import { SlotManipulatable } from "./SlotManipulatable.sol";
contract Proxy is SlotManipulatable {
bytes32 private constant FACTORY_SLOT = bytes32(0x7a45a402e4cb6e08ebc196f20f66d5d30e67285a2a8aa80503fa409e727a4af1);
bytes32 private constant IMPLEMENTATION_SLOT = bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc);
constructor(address factory_, address implementation_) {
_setSlotValue(FACTORY_SLOT, bytes32(uint256(uint160(factory_))));
address implementation = implementation_ == address(0)
? IDefaultImplementationBeacon(factory_).defaultImplementation()
: implementation_;
require(implementation != address(0));
_setSlotValue(IMPLEMENTATION_SLOT, bytes32(uint256(uint160(implementation))));
}
fallback() payable external virtual {
bytes32 implementation = _getSlotValue(IMPLEMENTATION_SLOT);
require(address(uint160(uint256(implementation))).code.length != uint256(0));
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}
文件 10 的 11:ProxyFactory.sol
pragma solidity ^0.8.7;
import { IProxied } from "./interfaces/IProxied.sol";
import { Proxy } from "./Proxy.sol";
abstract contract ProxyFactory {
mapping(uint256 => address) internal _implementationOf;
mapping(address => uint256) internal _versionOf;
mapping(uint256 => mapping(uint256 => address)) internal _migratorForPath;
function _getImplementationOfProxy(address proxy_) private view returns (bool success_, address implementation_) {
bytes memory returnData;
( success_, returnData ) = proxy_.staticcall(abi.encodeWithSelector(IProxied.implementation.selector));
implementation_ = abi.decode(returnData, (address));
}
function _initializeInstance(address proxy_, uint256 version_, bytes memory arguments_) private returns (bool success_) {
address initializer = _migratorForPath[version_][version_];
if (initializer == address(0)) return arguments_.length == uint256(0);
( success_, ) = proxy_.call(abi.encodeWithSelector(IProxied.migrate.selector, initializer, arguments_));
}
function _newInstance(uint256 version_, bytes memory arguments_) internal virtual returns (bool success_, address proxy_) {
address implementation = _implementationOf[version_];
if (implementation == address(0)) return (false, address(0));
proxy_ = address(new Proxy(address(this), implementation));
success_ = _initializeInstance(proxy_, version_, arguments_);
}
function _newInstance(bytes memory arguments_, bytes32 salt_) internal virtual returns (bool success_, address proxy_) {
proxy_ = address(new Proxy{ salt: salt_ }(address(this), address(0)));
( , address implementation ) = _getImplementationOfProxy(proxy_);
uint256 version = _versionOf[implementation];
success_ = (version != uint256(0)) && _initializeInstance(proxy_, version, arguments_);
}
function _registerImplementation(uint256 version_, address implementation_) internal virtual returns (bool success_) {
if (
version_ == uint256(0) ||
_implementationOf[version_] != address(0) ||
_versionOf[implementation_] != uint256(0) ||
!_isContract(implementation_)
) return false;
_implementationOf[version_] = implementation_;
_versionOf[implementation_] = version_;
return true;
}
function _registerMigrator(uint256 fromVersion_, uint256 toVersion_, address migrator_) internal virtual returns (bool success_) {
if (fromVersion_ == uint256(0) || toVersion_ == uint256(0)) return false;
if (migrator_ != address(0) && !_isContract(migrator_)) return false;
_migratorForPath[fromVersion_][toVersion_] = migrator_;
return true;
}
function _upgradeInstance(address proxy_, uint256 toVersion_, bytes memory arguments_) internal virtual returns (bool success_) {
if (!_isContract(proxy_)) return false;
address toImplementation = _implementationOf[toVersion_];
if (toImplementation == address(0)) return false;
address fromImplementation;
( success_, fromImplementation ) = _getImplementationOfProxy(proxy_);
if (!success_) return false;
( success_, ) = proxy_.call(abi.encodeWithSelector(IProxied.setImplementation.selector, toImplementation));
if (!success_) return false;
address migrator = _migratorForPath[_versionOf[fromImplementation]][toVersion_];
if (migrator == address(0)) return arguments_.length == uint256(0);
( success_, ) = proxy_.call(abi.encodeWithSelector(IProxied.migrate.selector, migrator, arguments_));
}
function _getDeterministicProxyAddress(bytes32 salt_) internal virtual view returns (address deterministicProxyAddress_) {
return address(
uint160(
uint256(
keccak256(
abi.encodePacked(
bytes1(0xff),
address(this),
salt_,
keccak256(abi.encodePacked(type(Proxy).creationCode, abi.encode(address(this), address(0))))
)
)
)
)
);
}
function _isContract(address account_) internal view returns (bool isContract_) {
return account_.code.length != uint256(0);
}
}
文件 11 的 11:SlotManipulatable.sol
pragma solidity ^0.8.7;
abstract contract SlotManipulatable {
function _getReferenceTypeSlot(bytes32 slot_, bytes32 key_) internal pure returns (bytes32 value_) {
return keccak256(abi.encodePacked(key_, slot_));
}
function _getSlotValue(bytes32 slot_) internal view returns (bytes32 value_) {
assembly {
value_ := sload(slot_)
}
}
function _setSlotValue(bytes32 slot_, bytes32 value_) internal {
assembly {
sstore(slot_, value_)
}
}
}
{
"compilationTarget": {
"contracts/MapleLoanFactory.sol": "MapleLoanFactory"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":contract-test-utils/=modules/erc20/modules/contract-test-utils/contracts/",
":ds-test/=modules/forge-std/lib/ds-test/src/",
":erc20-helper/=modules/erc20-helper/src/",
":erc20/=modules/erc20/",
":forge-std/=modules/forge-std/src/",
":maple-proxy-factory/=modules/maple-proxy-factory/",
":proxy-factory/=modules/maple-proxy-factory/modules/proxy-factory/"
]
}
[{"inputs":[{"internalType":"address","name":"mapleGlobals_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version_","type":"uint256"}],"name":"DefaultVersionSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version_","type":"uint256"},{"indexed":true,"internalType":"address","name":"implementationAddress_","type":"address"},{"indexed":true,"internalType":"address","name":"initializer_","type":"address"}],"name":"ImplementationRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version_","type":"uint256"},{"indexed":true,"internalType":"address","name":"instance_","type":"address"},{"indexed":false,"internalType":"bytes","name":"initializationArguments_","type":"bytes"}],"name":"InstanceDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"instance_","type":"address"},{"indexed":true,"internalType":"uint256","name":"fromVersion_","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"toVersion_","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"migrationArguments_","type":"bytes"}],"name":"InstanceUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"mapleGlobals_","type":"address"}],"name":"MapleGlobalsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromVersion_","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"toVersion_","type":"uint256"}],"name":"UpgradePathDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromVersion_","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"toVersion_","type":"uint256"},{"indexed":true,"internalType":"address","name":"migrator_","type":"address"}],"name":"UpgradePathEnabled","type":"event"},{"inputs":[{"internalType":"bytes","name":"arguments_","type":"bytes"},{"internalType":"bytes32","name":"salt_","type":"bytes32"}],"name":"createInstance","outputs":[{"internalType":"address","name":"instance_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultImplementation","outputs":[{"internalType":"address","name":"defaultImplementation_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"fromVersion_","type":"uint256"},{"internalType":"uint256","name":"toVersion_","type":"uint256"}],"name":"disableUpgradePath","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fromVersion_","type":"uint256"},{"internalType":"uint256","name":"toVersion_","type":"uint256"},{"internalType":"address","name":"migrator_","type":"address"}],"name":"enableUpgradePath","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"arguments_","type":"bytes"},{"internalType":"bytes32","name":"salt_","type":"bytes32"}],"name":"getInstanceAddress","outputs":[{"internalType":"address","name":"instanceAddress_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"version_","type":"uint256"}],"name":"implementationOf","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isInstance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isLoan","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mapleGlobals","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"oldVersion_","type":"uint256"},{"internalType":"uint256","name":"newVersion_","type":"uint256"}],"name":"migratorForPath","outputs":[{"internalType":"address","name":"migrator_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"version_","type":"uint256"},{"internalType":"address","name":"implementationAddress_","type":"address"},{"internalType":"address","name":"initializer_","type":"address"}],"name":"registerImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"version_","type":"uint256"}],"name":"setDefaultVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"mapleGlobals_","type":"address"}],"name":"setGlobals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"upgradeEnabledForPath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"toVersion_","type":"uint256"},{"internalType":"bytes","name":"arguments_","type":"bytes"}],"name":"upgradeInstance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"implementation_","type":"address"}],"name":"versionOf","outputs":[{"internalType":"uint256","name":"version_","type":"uint256"}],"stateMutability":"view","type":"function"}]