Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
a9ddbcf
Update ledger and compact-runtime packages to latest
emnul Feb 3, 2026
d04f428
Update package README
emnul Feb 3, 2026
d660ec9
Update files to latest
emnul Feb 3, 2026
03d7688
Update SimulatorConfig
emnul Feb 3, 2026
af52f9b
Merge branch 'main' into update-simulator-compiler
emnul Feb 3, 2026
3729159
Update simulator files
emnul Feb 3, 2026
3d5d13f
Update compact compiler package
emnul Feb 3, 2026
e6b9cb3
Update scripts with correct package name
emnul Feb 3, 2026
af905b5
Remove version file
emnul Feb 3, 2026
c60c581
Update compact version in CI workflow
emnul Feb 3, 2026
ddae866
lint files
emnul Feb 3, 2026
a6c11ca
Remove archive from compact task
emnul Feb 3, 2026
134017e
Update language version across contracts
emnul Feb 3, 2026
3af8a05
add private:true back to compact compiler package.json
emnul Feb 3, 2026
2c290f3
Revert "add private:true back to compact compiler package.json"
emnul Feb 3, 2026
9715f6b
avoid publishing compact package
emnul Feb 3, 2026
b78adc7
Merge branch 'update-simulator-compiler' into upgrade-contracts-versi…
emnul Feb 3, 2026
25955ce
Fixup contracts, rename circuit params to avoid keyword collision
emnul Feb 4, 2026
06aba18
Build tool workaround
emnul Feb 4, 2026
898e810
Update Mock token contracts
emnul Feb 4, 2026
bb91a60
Update file extensions
emnul Feb 4, 2026
9131479
Update package name
emnul Feb 4, 2026
52f90eb
Refactor constructorContext name
emnul Feb 4, 2026
62a75ca
Refactor PausableSimulator
emnul Feb 4, 2026
2bba9aa
Refactor InitializableSimulator
emnul Feb 4, 2026
fd8dc20
Remove unused deps
emnul Feb 4, 2026
246b433
Remove unused deps
emnul Feb 4, 2026
51ff923
Update UtilsSimulator
emnul Feb 4, 2026
24af2c3
Refactor token Witness files
emnul Feb 4, 2026
798099e
fmt file
emnul Feb 4, 2026
f923383
Refactor FungibleTokenSimulator
emnul Feb 5, 2026
bb6493e
Refactor MultiToken Simulator
emnul Feb 5, 2026
6de01b5
Refactor NonFungibleToken Simulator
emnul Feb 5, 2026
7511ab7
Refactor AccessControl, Ownable Witnesses
emnul Feb 5, 2026
958896f
Refactor ZOwnablePK Simulator
emnul Feb 5, 2026
23a4e97
Update AccessControl, Ownable Simulators
emnul Feb 5, 2026
4ba79ee
Update Ownable Simulator constructor args
emnul Feb 9, 2026
7ea556e
Update AccessControl, Ownable tests
emnul Feb 9, 2026
0cf6ebf
Remove old simulator interfaces
emnul Feb 9, 2026
76f04f9
Update address files
emnul Feb 9, 2026
ccbd060
Fix Pausable Simulator bug
emnul Feb 9, 2026
9930558
Update Initializable tests
emnul Feb 9, 2026
9139c25
Add missing contract circuit
emnul Feb 9, 2026
24c636d
Update tests
emnul Feb 9, 2026
278db51
Fix constructor type
emnul Feb 10, 2026
0fb0a40
Update MultiToken tests
emnul Feb 10, 2026
601193b
Update nonFungibleToken tests
emnul Feb 10, 2026
f4f4f5a
Refactor encodeToAddress util function
emnul Feb 10, 2026
aa02090
Exclude archive functions from tests
emnul Feb 10, 2026
6a2a80f
Lint files, improve witness typings
emnul Feb 10, 2026
185de94
Bump language versions
emnul Feb 11, 2026
bf1f08f
Update github workflows
emnul Feb 11, 2026
61e6d4e
Update compact tool docs
emnul Feb 11, 2026
10213a9
Update sample file versions
emnul Feb 11, 2026
c57d50a
Merge branch 'main' into upgrade-contracts-versions-0.28.0
emnul Feb 11, 2026
d0779ba
Simplify empty witness files
emnul Feb 11, 2026
8c38e2b
Refactor as(caller) pattern
emnul Feb 11, 2026
961b0db
fmt files
emnul Feb 12, 2026
6c2b90d
Refactor as(caller) pattern in tests
emnul Feb 12, 2026
e01afe6
Define import path for test-utils/address.js
emnul Feb 12, 2026
caedef3
Centralize test-utils
emnul Feb 12, 2026
14de110
Redefine utils import using new subpath import
emnul Feb 12, 2026
1b01a62
remove duplicate code
emnul Feb 12, 2026
de1f2cc
lint files
emnul Feb 12, 2026
23cc1f5
remove unused type
emnul Feb 12, 2026
ea59fec
Update docs
emnul Feb 12, 2026
41f2d2f
Remove unused private state var from sims
emnul Feb 13, 2026
3e20269
lint file
emnul Feb 13, 2026
4c44062
Remove unused param from method docs
emnul Feb 13, 2026
ddc5880
Update contracts/src/token/test/FungibleToken.test.ts
emnul Feb 13, 2026
7dd8a81
Update contracts/src/token/test/FungibleToken.test.ts
emnul Feb 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/ISSUE_TEMPLATE/01_bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ body:
label: Version
description: What version of Compact are you running?
options:
- 0.26.0 (Default)
- 0.29.0 (Default)
default: 0
validations:
required: true

4 changes: 2 additions & 2 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ runs:

- name: Setup Compact Compiler
if: ${{ inputs.skip-compact != 'true' }}
uses: midnightntwrk/setup-compact-action@4130145456ad3f45934788dd4a65647eb283e658 # loose commit/not released
uses: midnightntwrk/setup-compact-action@836895c8fffbbea6bd986af2b17e8941ff29d1f8 # v1
with:
compact-version: "0.26.0"
compact-version: "0.29.0"
3 changes: 3 additions & 0 deletions contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
},
"homepage": "https://docs.openzeppelin.com/contracts-compact/",
"type": "module",
"imports": {
"#test-utils/address.js": "./test-utils/address.js"
},
"scripts": {
"compact": "compact-compiler",
"compact:access": "compact-compiler --dir access",
Expand Down
129 changes: 71 additions & 58 deletions contracts/src/access/AccessControl.compact
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Compact Contracts v0.0.1-alpha.1 (access/AccessControl.compact)

pragma language_version >= 0.18.0;
pragma language_version >= 0.21.0;

/**
* @module AccessControl
Expand Down Expand Up @@ -81,7 +81,8 @@ module AccessControl {
* @type {Map<roleId, hasRole>}
* @type {Map<Bytes<32>, Map<Either<ZswapCoinPublicKey, ContractAddress>, Boolean>} _operatorRoles
 */
export ledger _operatorRoles: Map<Bytes<32>, Map<Either<ZswapCoinPublicKey, ContractAddress>, Boolean>>;
export ledger _operatorRoles: Map<Bytes<32>,
Map<Either<ZswapCoinPublicKey, ContractAddress>, Boolean>>;

/**
* @description Mapping from a role identifier to an admin role identifier.
Expand All @@ -94,25 +95,21 @@ module AccessControl {

export ledger DEFAULT_ADMIN_ROLE: Bytes<32>;

/**
* @description Returns `true` if `account` has been granted `roleId`.
*
* @circuitInfo k=10, rows=487
*
* @param {Bytes<32>} roleId - The role identifier.
* @param {Either<ZswapCoinPublicKey, ContractAddress>} account - The account to query.
* @return {Boolean} - Whether the account has the specified role.
/**
* @description Returns `true` if `account` has been granted `roleId`.
*
* @circuitInfo k=10, rows=487
*
* @param {Bytes<32>} roleId - The role identifier.
* @param {Either<ZswapCoinPublicKey, ContractAddress>} account - The account to query.
* @return {Boolean} - Whether the account has the specified role.
  */
export circuit hasRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>): Boolean {
if (
_operatorRoles.member(disclose(roleId)) &&
_operatorRoles
.lookup(roleId)
.member(disclose(account))
) {
return _operatorRoles
.lookup(roleId)
.lookup(disclose(account));
export circuit hasRole(roleId: Bytes<32>,
account: Either<ZswapCoinPublicKey, ContractAddress>
): Boolean {
if (_operatorRoles.member(disclose(roleId)) &&
_operatorRoles.lookup(roleId).member(disclose(account))) {
return _operatorRoles.lookup(roleId).lookup(disclose(account));
} else {
return false;
}
Expand All @@ -132,7 +129,7 @@ module AccessControl {
* @return {[]} - Empty tuple.
*/
export circuit assertOnlyRole(roleId: Bytes<32>): [] {
_checkRole(roleId, left<ZswapCoinPublicKey,ContractAddress>(ownPublicKey()));
_checkRole(roleId, left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey()));
}

/**
Expand All @@ -148,7 +145,10 @@ module AccessControl {
* @param {Either<ZswapCoinPublicKey, ContractAddress>} account - The account to query.
* @return {[]} - Empty tuple.
*/
export circuit _checkRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>): [] {
export circuit _checkRole(
roleId: Bytes<32>,
account: Either<ZswapCoinPublicKey, ContractAddress>
): [] {
assert(hasRole(roleId, account), "AccessControl: unauthorized account");
}

Expand Down Expand Up @@ -184,7 +184,10 @@ module AccessControl {
* @param {Either<ZswapCoinPublicKey, ContractAddress>} account - A ZswapCoinPublicKey or ContractAddress.
* @return {[]} - Empty tuple.
*/
export circuit grantRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>): [] {
export circuit grantRole(
roleId: Bytes<32>,
account: Either<ZswapCoinPublicKey, ContractAddress>
): [] {
assertOnlyRole(getRoleAdmin(roleId));
_grantRole(roleId, account);
}
Expand All @@ -202,31 +205,39 @@ module AccessControl {
* @param {Either<ZswapCoinPublicKey, ContractAddress>} account - A ZswapCoinPublicKey or ContractAddress.
* @return {[]} - Empty tuple.
*/
export circuit revokeRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>): [] {
export circuit revokeRole(
roleId: Bytes<32>,
account: Either<ZswapCoinPublicKey, ContractAddress>
): [] {
assertOnlyRole(getRoleAdmin(roleId));
_revokeRole(roleId, account);
}

/**
* @description Revokes `roleId` from the calling account.
*
* @notice Roles are often managed via {grantRole} and {revokeRole}: this circuit's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* @circuitInfo k=10, rows=640
*
* Requirements:
*
* - The caller must be `callerConfirmation`.
* - The caller must not be a `ContractAddress`.
*
* @param {Bytes<32>} roleId - The role identifier.
* @param {Either<ZswapCoinPublicKey, ContractAddress>} callerConfirmation - A ZswapCoinPublicKey or ContractAddress.
* @return {[]} - Empty tuple.
*/
export circuit renounceRole(roleId: Bytes<32>, callerConfirmation: Either<ZswapCoinPublicKey, ContractAddress>): [] {
assert(callerConfirmation == left<ZswapCoinPublicKey,ContractAddress>(ownPublicKey()), "AccessControl: bad confirmation");
/**
* @description Revokes `roleId` from the calling account.
*
* @notice Roles are often managed via {grantRole} and {revokeRole}: this circuit's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* @circuitInfo k=10, rows=640
*
* Requirements:
*
* - The caller must be `callerConfirmation`.
* - The caller must not be a `ContractAddress`.
*
* @param {Bytes<32>} roleId - The role identifier.
* @param {Either<ZswapCoinPublicKey, ContractAddress>} callerConfirmation - A ZswapCoinPublicKey or ContractAddress.
* @return {[]} - Empty tuple.
*/
export circuit renounceRole(
roleId: Bytes<32>,
callerConfirmation: Either<ZswapCoinPublicKey, ContractAddress>
): [] {
assert(callerConfirmation == left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey()),
"AccessControl: bad confirmation"
);

_revokeRole(roleId, callerConfirmation);
}
Expand Down Expand Up @@ -258,7 +269,10 @@ module AccessControl {
* @param {Either<ZswapCoinPublicKey, ContractAddress>} account - A ZswapCoinPublicKey or ContractAddress.
* @return {Boolean} roleGranted - A boolean indicating if `roleId` was granted.
*/
export circuit _grantRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>): Boolean {
export circuit _grantRole(
roleId: Bytes<32>,
account: Either<ZswapCoinPublicKey, ContractAddress>
): Boolean {
assert(!Utils_isContractAddress(account), "AccessControl: unsafe role approval");
return _unsafeGrantRole(roleId, account);
}
Expand All @@ -276,22 +290,20 @@ module AccessControl {
* @param {Either<ZswapCoinPublicKey, ContractAddress>} account - A ZswapCoinPublicKey or ContractAddress.
* @return {Boolean} roleGranted - A boolean indicating if `role` was granted.
*/
export circuit _unsafeGrantRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>): Boolean {
export circuit _unsafeGrantRole(
roleId: Bytes<32>,
account: Either<ZswapCoinPublicKey, ContractAddress>
): Boolean {
if (hasRole(roleId, account)) {
return false;
}

if (!_operatorRoles.member(disclose(roleId))) {
_operatorRoles.insert(
disclose(roleId),
default<Map<
Either<ZswapCoinPublicKey, ContractAddress>,
Boolean
>>
);
_operatorRoles
.lookup(roleId)
.insert(disclose(account), true);
default<Map<Either<ZswapCoinPublicKey, ContractAddress>, Boolean>>
);
_operatorRoles.lookup(roleId).insert(disclose(account), true);
return true;
}

Expand All @@ -309,14 +321,15 @@ module AccessControl {
* @param {Bytes<32>} adminRole - The admin role identifier.
* @return {Boolean} roleRevoked - A boolean indicating if `roleId` was revoked.
*/
export circuit _revokeRole(roleId: Bytes<32>, account: Either<ZswapCoinPublicKey, ContractAddress>): Boolean {
export circuit _revokeRole(
roleId: Bytes<32>,
account: Either<ZswapCoinPublicKey, ContractAddress>
): Boolean {
if (!hasRole(roleId, account)) {
return false;
}

_operatorRoles
.lookup(roleId)
.insert(disclose(account), false);
_operatorRoles.lookup(roleId).insert(disclose(account), false);
return true;
}
}
8 changes: 5 additions & 3 deletions contracts/src/access/Ownable.compact
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Compact Contracts v0.0.1-alpha.1 (access/Ownable.compact)

pragma language_version >= 0.18.0;
pragma language_version >= 0.21.0;

/**
* @module Ownable
Expand Down Expand Up @@ -143,7 +143,7 @@ module Ownable {
export circuit renounceOwnership(): [] {
Initializable_assertInitialized();
assertOnlyOwner();
_transferOwnership(burnAddress());
_transferOwnership(shieldedBurnAddress());
}

/**
Expand Down Expand Up @@ -206,7 +206,9 @@ module Ownable {
* @param {Either<ZswapCoinPublicKey, ContractAddress>} newOwner - The new owner.
* @returns {[]} Empty tuple.
*/
export circuit _unsafeUncheckedTransferOwnership(newOwner: Either<ZswapCoinPublicKey, ContractAddress>): [] {
export circuit _unsafeUncheckedTransferOwnership(
newOwner: Either<ZswapCoinPublicKey, ContractAddress>
): [] {
Initializable_assertInitialized();
_owner = disclose(newOwner);
}
Expand Down
35 changes: 14 additions & 21 deletions contracts/src/access/ZOwnablePK.compact
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Compact Contracts v0.0.1-alpha.1 (access/ZOwnablePK.compact)

pragma language_version >= 0.18.0;
pragma language_version >= 0.21.0;

/**
* @module ZOwnablePK
Expand Down Expand Up @@ -191,13 +191,14 @@ module ZOwnablePK {
Initializable_assertInitialized();

const nonce = wit_secretNonce();
const callerAsEither = Either<ZswapCoinPublicKey, ContractAddress> {
is_left: true,
left: ownPublicKey(),
right: ContractAddress { bytes: pad(32, "") }
};
const callerAsEither =
Either<ZswapCoinPublicKey, ContractAddress> { is_left: true,
left: ownPublicKey(),
right: ContractAddress { bytes: pad(32, "") } };
const id = _computeOwnerId(callerAsEither, nonce);
assert(_ownerCommitment == _computeOwnerCommitment(id, _counter), "ZOwnablePK: caller is not the owner");
assert(_ownerCommitment == _computeOwnerCommitment(id, _counter),
"ZOwnablePK: caller is not the owner"
);
}

/**
Expand Down Expand Up @@ -232,19 +233,11 @@ module ZOwnablePK {
* after every transfer to prevent duplicate commitments given the same `id`.
* @returns {Bytes<32>} The commitment derived from `id` and `counter`.
*/
export circuit _computeOwnerCommitment(
id: Bytes<32>,
counter: Uint<64>,
): Bytes<32> {
export circuit _computeOwnerCommitment(id: Bytes<32>, counter: Uint<64>,): Bytes<32> {
Initializable_assertInitialized();
return persistentHash<Vector<4, Bytes<32>>>(
[
id,
_instanceSalt,
counter as Field as Bytes<32>,
pad(32, "ZOwnablePK:shield:")
]
);
[id, _instanceSalt, counter as Field as Bytes<32>, pad(32, "ZOwnablePK:shield:")]
);
}

/**
Expand Down Expand Up @@ -280,9 +273,9 @@ module ZOwnablePK {
* @returns {Bytes<32>} The computed owner ID.
*/
export pure circuit _computeOwnerId(
pk: Either<ZswapCoinPublicKey, ContractAddress>,
nonce: Bytes<32>
): Bytes<32> {
pk: Either<ZswapCoinPublicKey, ContractAddress>,
nonce: Bytes<32>
): Bytes<32> {
assert(pk.is_left, "ZOwnablePK: contract address owners are not yet supported");

return persistentHash<Vector<2, Bytes<32>>>([pk.left.bytes, nonce]);
Expand Down
Loading