Skip to content

Commit 94ae899

Browse files
authored
Merge pull request #40 from metacontract/dev/devkit
Update Base Contracts & Add Dictionary Deployment Types
2 parents ae5b8a9 + c96fc5f commit 94ae899

40 files changed

+321
-347
lines changed

devkit/MCScript.sol

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.24;
33

4-
import {System} from "devkit/system/System.sol";
5-
64
// 💬 ABOUT
75
// Meta Contract's default Script based on Forge Std Script
86

97
// 📦 BOILERPLATE
108
import {MCScriptBase} from "./MCBase.sol";
119

1210
// ⭐️ MC SCRIPT
13-
abstract contract MCScript is MCScriptBase {
14-
constructor() {
15-
if (System.Config().SETUP.STD_FUNCS) mc.setupStdFunctions();
16-
}
17-
}
11+
abstract contract MCScript is MCScriptBase {}

devkit/MCTest.sol

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,28 @@ import {System} from "devkit/system/System.sol";
77
import {Receive} from "mc-std/functions/Receive.sol";
88
import {Formatter} from "devkit/types/Formatter.sol";
99
import {ProxyUtils} from "@ucs.mc/proxy/ProxyUtils.sol";
10-
import {Dummy} from "test/utils/Dummy.sol";
10+
import {Dummy} from "devkit/test/dummy/Dummy.sol";
1111

1212
// 💬 ABOUT
1313
// Meta Contract's default Test based on Forge Std Test
1414

1515
// 📦 BOILERPLATE
1616
import {MCTestBase} from "./MCBase.sol";
1717

18-
// ⭐️ MC TEST
19-
abstract contract MCTest is MCTestBase {
20-
constructor() {
21-
if (System.Config().SETUP.STD_FUNCS) mc.setupStdFunctions();
22-
}
18+
struct Function {
19+
bytes4 selector;
20+
address implementation;
2321
}
2422

2523
// 🌟 MC State Fuzzing Test
26-
abstract contract MCStateFuzzingTest is MCTestBase, OZProxy { // solhint-disable-line payable-fallback
27-
struct Function {
28-
bytes4 selector;
29-
address implementation;
30-
}
31-
24+
abstract contract MCTest is MCTestBase, OZProxy { // solhint-disable-line payable-fallback
3225
mapping(bytes4 selector => address) implementations;
3326
address target = address(this);
3427
Function[] internal functions;
3528
address dictionary;
3629

3730
constructor() {
38-
// System.Config().load();
39-
implementations[bytes4(0)] = address(new Receive());
31+
_use(bytes4(0), address(new Receive()));
4032
}
4133

4234
function _use(bytes4 selector_, address impl_) internal {

devkit/core/Dictionary.sol

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import {Validator} from "devkit/system/Validator.sol";
1212
import {ForgeHelper} from "devkit/utils/ForgeHelper.sol";
1313

1414
// External Libs
15-
import {IDictionary} from "@ucs.mc/dictionary/IDictionary.sol";
15+
import {IDictionary} from "@ucs.mc/dictionary/interfaces/IDictionary.sol";
1616
import {Dictionary as UCSDictionary} from "@ucs.mc/dictionary/Dictionary.sol";
17+
import {ImmutableDictionary, Function as Func} from "@ucs.mc/dictionary/ImmutableDictionary.sol";
18+
import {BeaconDictionary} from "@ucs.mc/dictionary/BeaconDictionary.sol";
1719
// Mock
18-
import {MockDictionary} from "devkit/mocks/MockDictionary.sol";
20+
import {MockDictionary} from "devkit/test/mocks/MockDictionary.sol";
1921

2022
// Core Types
2123
import {Function} from "devkit/core/Function.sol";
@@ -60,6 +62,9 @@ library DictionaryLib {
6062

6163
/**-------------------------
6264
🚀 Deploy Dictionary
65+
- Verifiable
66+
- Immutable
67+
- Beacon
6368
---------------------------*/
6469
function deploy(address owner) internal returns(Dictionary memory dictionary) {
6570
uint pid = dictionary.startProcess("deploy", param(owner));
@@ -71,6 +76,31 @@ library DictionaryLib {
7176
return dictionary.finishProcess(pid);
7277
}
7378

79+
function deployImmutable(Function[] storage functions, address facade) internal returns(Dictionary memory dictionary) {
80+
uint pid = dictionary.startProcess("deployImmutable", param(functions, facade));
81+
Validator.SHOULD_FacadeIsContract(facade);
82+
dictionary.startBuilding();
83+
Func[] memory funcs;
84+
for (uint i; i < functions.length; ++i) {
85+
funcs[i] = Func(functions[i].selector, functions[i].implementation);
86+
}
87+
dictionary.addr = address(new ImmutableDictionary(funcs, facade));
88+
dictionary.kind = DictionaryKind.Immutable;
89+
dictionary.finishBuilding();
90+
return dictionary.finishProcess(pid);
91+
}
92+
93+
function deployBeacon(address implementation, address owner) internal returns(Dictionary memory dictionary) {
94+
uint pid = dictionary.startProcess("deployBeacon", param(implementation, owner));
95+
Validator.MUST_AddressIsContract(implementation);
96+
Validator.SHOULD_OwnerIsNotZeroAddress(owner);
97+
dictionary.startBuilding();
98+
dictionary.addr = address(new BeaconDictionary(implementation, owner));
99+
dictionary.kind = DictionaryKind.Beacon;
100+
dictionary.finishBuilding();
101+
return dictionary.finishProcess(pid);
102+
}
103+
74104
/**-----------------------
75105
📩 Load Dictionary
76106
-------------------------*/
@@ -114,7 +144,7 @@ library DictionaryLib {
114144
function set(Dictionary memory dictionary, bytes4 selector, address implementation) internal returns(Dictionary memory) {
115145
uint pid = dictionary.startProcess("set", param(selector, implementation));
116146
Validator.MUST_Completed(dictionary);
117-
Validator.MUST_NotEmptySelector(selector);
147+
Validator.SHOULD_NotEmptySelector(selector);
118148
Validator.MUST_AddressIsContract(implementation);
119149
IDictionary(dictionary.addr).setImplementation({
120150
functionSelector: selector,
@@ -177,6 +207,8 @@ library DictionaryLib {
177207
enum DictionaryKind {
178208
undefined,
179209
Verifiable,
210+
Immutable,
211+
Beacon,
180212
Mock
181213
}
182214
using Inspector for DictionaryKind global;

devkit/core/Proxy.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {Validator} from "devkit/system/Validator.sol";
1212
// External Lib Contract
1313
import {Proxy as UCSProxy} from "@ucs.mc/proxy/Proxy.sol";
1414
// Mock Contract
15-
import {SimpleMockProxy} from "devkit/mocks/SimpleMockProxy.sol";
15+
import {SimpleMockProxy} from "devkit/test/mocks/SimpleMockProxy.sol";
1616

1717
// Core Types
1818
import {Dictionary} from "devkit/core/Dictionary.sol";

devkit/system/Tracer.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ function param(Function[] memory functions) pure returns(string memory res) {
347347
res = res.comma(functions[i].name);
348348
}
349349
}
350+
function param(Function[] memory functions, address facade) pure returns(string memory res) {
351+
return param(functions).comma(facade);
352+
}
350353

351354
function param(Bundle memory bundle) pure returns(string memory) {
352355
return bundle.name;

devkit/system/Validator.sol

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,15 @@ library Validator {
7373
function MUST_NotEmptyEnvKey(string memory envKey) internal view {
7474
validate(MUST, envKey.isNotEmpty(), HEAD.ENV_KEY_REQUIRED, BODY.ENV_KEY_REQUIRED);
7575
}
76-
function MUST_NotEmptySelector(bytes4 selector) internal view {
77-
validate(MUST, selector.isNotEmpty(), HEAD.SELECTOR_REQUIRED, BODY.SELECTOR_REQUIRED);
76+
function SHOULD_NotEmptySelector(bytes4 selector) internal view {
77+
validate(SHOULD, selector.isNotEmpty(), HEAD.SELECTOR_RECOMMENDED, BODY.SELECTOR_RECOMMENDED);
7878
}
7979
function MUST_AddressIsContract(address addr) internal view {
8080
validate(MUST, addr.isContract(), HEAD.ADDRESS_NOT_CONTRACT, BODY.ADDRESS_NOT_CONTRACT);
8181
}
82+
function SHOULD_FacadeIsContract(address facade) internal view {
83+
validate(SHOULD, facade.isContract(), HEAD.FACADE_NOT_CONTRACT, BODY.FACADE_NOT_CONTRACT);
84+
}
8285
function SHOULD_OwnerIsNotZeroAddress(address owner) internal view {
8386
validate(MUST, owner.isNotZero(), HEAD.OWNER_ZERO_ADDRESS_RECOMMENDED, BODY.OWNER_ZERO_ADDRESS_RECOMMENDED);
8487
}
@@ -96,7 +99,6 @@ library Validator {
9699
function ValidateBuilder(Function storage func) internal view returns(bool) {
97100
return (
98101
validate(COMPLETION, func.name.isAssigned(), HEAD.FUNC_NAME_UNASSIGNED, BODY.FUNC_NAME_UNASSIGNED) &&
99-
validate(COMPLETION, func.selector.isAssigned(), HEAD.FUNC_SELECTOR_UNASSIGNED, BODY.FUNC_SELECTOR_UNASSIGNED) &&
100102
validate(COMPLETION, func.implementation.isContract(), HEAD.FUNC_CONTRACT_UNASSIGNED, BODY.FUNC_CONTRACT_UNASSIGNED)
101103
);
102104
}

devkit/system/message/MessageBody.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ library MessageBody {
99
// Primitives
1010
string constant NAME_REQUIRED = "The provided name cannot be an empty string. Please enter a non-empty value for the name and try again.";
1111
string constant ENV_KEY_REQUIRED = "The provided environment key cannot be an empty string. Please enter a non-empty value for the key and try again.";
12-
string constant SELECTOR_REQUIRED = "The provided function selector cannot be empty (0x00000000). Please provide a non-empty 4-byte selector value and try again.";
12+
string constant SELECTOR_RECOMMENDED = "The provided function selector is empty (0x00000000). It is recommended to use a non-empty selector.";
1313
string constant ADDRESS_NOT_CONTRACT = "The provided address is not a contract address. Please provide the address of a deployed contract and try again.";
14+
string constant FACADE_NOT_CONTRACT = "The provided facade address is not a contract address. It is recommended to use the address of a deployed facade contract and try again.";
1415
string constant OWNER_ZERO_ADDRESS_RECOMMENDED = "The provided owner address is the zero address (0x0). It is recommended to use a non-zero address for the owner to ensure proper access control and security.";
1516
// Current Context
1617
string constant CURRENT_NAME_NOT_FOUND = "Current Name Not Found";
1718
// Function
1819
string constant FUNC_NAME_UNASSIGNED = "The function name is currently unassigned. It is recommended to provide a non-empty value for the name.";
19-
string constant FUNC_SELECTOR_UNASSIGNED = "The 4-byte function selector is currently unassigned. It is recommended to provide a non-zero value for the selector.";
2020
string constant FUNC_CONTRACT_UNASSIGNED = "The implementation contract address is currently unassigned. It is recommended to set the address of a deployed contract.";
2121
string constant FUNC_NOT_COMPLETE = "The function is not marked as complete. Please ensure all requirements are met before proceeding.";
2222
string constant FUNC_LOCKED = "The function object is currently locked and cannot be modified.";

devkit/system/message/MessageHead.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ library MessageHead {
99
// Primitives
1010
string constant NAME_REQUIRED = "Name Required";
1111
string constant ENV_KEY_REQUIRED = "EnvKey Required";
12-
string constant SELECTOR_REQUIRED = "Selector Required";
12+
string constant SELECTOR_RECOMMENDED = "Empty Selector";
1313
string constant ADDRESS_NOT_CONTRACT = "Address Not Contract";
14+
string constant FACADE_NOT_CONTRACT = "Facade Not Contract";
1415
string constant OWNER_ZERO_ADDRESS_RECOMMENDED = "Owner Zero Address";
1516
// Current Context
1617
string constant CURRENT_NAME_NOT_FOUND = "Current Name Not Found";
1718
// Function
1819
string constant FUNC_NAME_UNASSIGNED = "Function Name Unassigned";
19-
string constant FUNC_SELECTOR_UNASSIGNED = "Function Selector Unassigned";
2020
string constant FUNC_CONTRACT_UNASSIGNED = "Implementation Contract Unassigned";
2121
string constant FUNC_NOT_COMPLETE = "Function Not Complete";
2222
string constant FUNC_LOCKED = "Function Locked";

test/utils/Dummy.sol renamed to devkit/test/dummy/Dummy.sol

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,26 @@ pragma solidity ^0.8.24;
44
import {MCDevKit} from "devkit/MCDevKit.sol";
55
import {DummyFunction} from "./DummyFunction.sol";
66
import {DummyFacade} from "./DummyFacade.sol";
7-
import {DummyContract} from "test/utils/DummyContract.sol";
8-
import {MCStateFuzzingTest} from "devkit/MCTest.sol";
7+
import {DummyContract} from "devkit/test/dummy/DummyContract.sol";
8+
import {Function} from "devkit/MCTest.sol";
99

1010
library Dummy {
11+
function bundleName() internal returns(string memory) {
12+
return "DummyBundleName";
13+
}
14+
15+
function functionSelector() internal returns(bytes4) {
16+
return DummyFunction.dummy.selector;
17+
}
18+
19+
function functionAddress() internal returns(address) {
20+
return address(new DummyFunction());
21+
}
22+
23+
function facadeAddress() internal returns(address) {
24+
return address(new DummyFacade());
25+
}
26+
1127
function setBundle(MCDevKit storage mc) internal {
1228
mc.init("DummyBundle");
1329
mc.use(DummyFunction.dummy.selector, address(new DummyFunction()));
@@ -19,7 +35,7 @@ library Dummy {
1935
return mc.createMockDictionary().addr;
2036
}
2137

22-
function dictionary(MCDevKit storage mc, MCStateFuzzingTest.Function[] memory functions) internal returns(address) {
38+
function dictionary(MCDevKit storage mc, Function[] memory functions) internal returns(address) {
2339
mc.init("DummyBundle");
2440
for (uint i; i < functions.length; ++i) {
2541
mc.use(functions[i].selector, functions[i].implementation);
File renamed without changes.
File renamed without changes.
File renamed without changes.

devkit/mocks/MockDictionary.sol renamed to devkit/test/mocks/MockDictionary.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {Dictionary} from "@ucs.mc/dictionary/Dictionary.sol";
1212
contract MockDictionary is Dictionary {
1313
constructor (address owner, Function[] memory functions) Dictionary(owner) {
1414
for (uint i; i < functions.length; ++i) {
15-
setImplementation(functions[i].selector, functions[i].implementation);
15+
_setImplementation(functions[i].selector, functions[i].implementation);
1616
}
1717
}
1818
}

devkit/types/Inspector.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {Inspector} from "devkit/types/Inspector.sol";
66
import {TypeStatus} from "devkit/types/TypeGuard.sol";
77
import {ForgeHelper} from "devkit/utils/ForgeHelper.sol";
88
// External Library
9-
import {IDictionary} from "@ucs.mc/dictionary/IDictionary.sol";
9+
import {IDictionary} from "@ucs.mc/dictionary/interfaces/IDictionary.sol";
1010
import {IBeacon as IVerifiable} from "@oz.mc/proxy/beacon/IBeacon.sol";
1111
// Core Types
1212
import {Function} from "devkit/core/Function.sol";

devkit/utils/global/MCDeployLib.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ import {NameGenerator} from "devkit/utils/mapping/NameGenerator.sol";
2626
/************************************
2727
* 🚀 Deployment
2828
* 🌞 Deploy Meta Contract
29+
* - Deploy
30+
* - DeployImmutable
31+
* - DeployRestrictedUpgradeable
32+
* - DeployContractUpgradeable
2933
* 🏠 Deploy Proxy
3034
* 📚 Deploy Dictionary
3135
* 🔂 Duplicate Dictionary
@@ -168,6 +172,7 @@ library MCDeployLib {
168172
mc.finishProcess(pid);
169173
}
170174

175+
171176
/**------------------------
172177
💽 Load Dictionary
173178
--------------------------*/

devkit/utils/global/MCHelpers.sol

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.24;
33

4-
// Forge-std
5-
import {Vm, VmSafe} from "forge-std/Vm.sol";
6-
// Constants
7-
/// @dev address(uint160(uint256(keccak256("hevm cheat code"))));
8-
Vm constant vm = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
9-
104
import {ProxyUtils} from "@ucs.mc/proxy/ProxyUtils.sol";
115

126
import {Logger} from "devkit/system/Logger.sol";
@@ -18,7 +12,7 @@ import {MCDevKit} from "devkit/MCDevKit.sol";
1812
import {System} from "devkit/system/System.sol";
1913
// Utils
2014
import {param} from "devkit/system/Tracer.sol";
21-
import {ForgeHelper} from "devkit/utils/ForgeHelper.sol";
15+
import {ForgeHelper, vm} from "devkit/utils/ForgeHelper.sol";
2216
// Core
2317
// functions
2418
import {Bundle} from "devkit/core/Bundle.sol";
@@ -131,4 +125,12 @@ library MCHelpers {
131125
function resumeBroadcast(MCDevKit storage, bool isBroadcasting, address currentSender) internal {
132126
ForgeHelper.resumeBroadcast(isBroadcasting, currentSender);
133127
}
128+
129+
130+
/**----------------------
131+
🛠️ Forge Extender
132+
------------------------*/
133+
function expectRevert(MCDevKit storage, string memory message) internal {
134+
vm.expectRevert(bytes(message));
135+
}
134136
}

devkit/utils/global/MCInitLib.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ library MCInitLib {
4343
uint pid = mc.startProcess("use", param(name, selector, implementation));
4444
// Register new function
4545
Validator.MUST_NotEmptyName(name);
46-
Validator.MUST_NotEmptySelector(selector);
46+
Validator.SHOULD_NotEmptySelector(selector);
4747
Validator.MUST_AddressIsContract(implementation);
4848
mc.functions.register(name, selector, implementation);
4949
// Push to current bundle
@@ -54,8 +54,8 @@ library MCInitLib {
5454
function use(MCDevKit storage mc, bytes4 selector, address implementation) internal returns(MCDevKit storage) {
5555
return use(mc, ForgeHelper.getLabel(implementation), selector, implementation);
5656
}
57-
function use(MCDevKit storage mc, Function storage functionInfo) internal returns(MCDevKit storage) {
58-
return use(mc, functionInfo.name, functionInfo.selector, functionInfo.implementation);
57+
function use(MCDevKit storage mc, Function storage func) internal returns(MCDevKit storage) {
58+
return use(mc, func.name, func.selector, func.implementation);
5959
}
6060
function use(MCDevKit storage mc, string memory functionName) internal returns(MCDevKit storage) {
6161
return use(mc, mc.functions.find(functionName));

foundry.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ libs = ["lib"]
55
optimizer = false
66
fs_permissions = [{ access = "read", path = "./mc.toml" }, { access = "read", path = "./lib/mc/mc.toml" }]
77

8+
evm_version = "cancun"
9+
810
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options

script/DeployLib.sol

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,22 @@
22
pragma solidity ^0.8.24;
33

44
import {MCDevKit} from "devkit/MCDevKit.sol";
5+
import {StdFacade} from "mc-std/interfaces/StdFacade.sol";
6+
import {InitSetAdmin} from "mc-std/functions/protected/InitSetAdmin.sol";
57

68
library DeployLib {
79
using DeployLib for MCDevKit;
810
string internal constant BUNDLE_NAME = "Std";
911

12+
function deployStd(MCDevKit storage mc, address admin) internal returns(address) {
13+
for (uint i; i < mc.std.all.functions.length; ++i) {
14+
mc.use(mc.std.all.functions[i]);
15+
}
16+
mc.useFacade(address(new StdFacade()));
17+
bytes memory initData = abi.encodeCall(InitSetAdmin.initSetAdmin, admin);
18+
return mc.deploy(initData).toProxyAddress();
19+
}
20+
1021
function deployStdFunctions(MCDevKit storage mc) internal returns(MCDevKit storage) {
1122
mc.std.functions.deployIfNotExists();
1223
return mc;

src/std/functions/GetFunctions.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
pragma solidity ^0.8.22;
33

44
import {ProxyUtils} from "@ucs.mc/proxy/ProxyUtils.sol";
5-
import {IDictionary} from "@ucs.mc/dictionary/IDictionary.sol";
5+
import {IDictionary} from "@ucs.mc/dictionary/interfaces/IDictionary.sol";
66

77
/** < MC Standard Function >
88
* @title GetFunctions

0 commit comments

Comments
 (0)