diff --git a/packages/protocol/src/settlement/contracts/DispatchSmartContract.ts b/packages/protocol/src/settlement/contracts/DispatchSmartContract.ts index 74d765e46..3e4de1ab1 100644 --- a/packages/protocol/src/settlement/contracts/DispatchSmartContract.ts +++ b/packages/protocol/src/settlement/contracts/DispatchSmartContract.ts @@ -1,6 +1,7 @@ import { AccountUpdate, Bool, + DeployArgs, Field, method, Poseidon, @@ -13,6 +14,7 @@ import { state, TokenId, UInt64, + Permissions, } from "o1js"; import { InMemoryMerkleTreeStorage, TypedClass } from "@proto-kit/common"; @@ -42,7 +44,6 @@ export interface DispatchContractType { executedMessagesHash: Field, newPromisedMessagesHash: Field ) => Promise; - initialize: (settlementContract: PublicKey) => Promise; enableTokenDeposits: ( tokenId: Field, bridgeContractAddress: PublicKey, @@ -50,6 +51,12 @@ export interface DispatchContractType { ) => Promise; promisedMessagesHash: State; + + deployAndInitialize: ( + args: DeployArgs | undefined, + permissions: Permissions, + settlementContract: PublicKey + ) => Promise; } const tokenBridgeRoot = new TokenBridgeTree( @@ -116,12 +123,6 @@ export abstract class DispatchSmartContractBase extends SmartContract { } protected initializeBase(settlementContract: PublicKey) { - this.promisedMessagesHash.getAndRequireEquals().assertEquals(Field(0)); - this.honoredMessagesHash.getAndRequireEquals().assertEquals(Field(0)); - this.settlementContract - .getAndRequireEquals() - .assertEquals(PublicKey.empty()); - this.promisedMessagesHash.set(ACTIONS_EMPTY_HASH); this.honoredMessagesHash.set(ACTIONS_EMPTY_HASH); this.settlementContract.set(settlementContract); @@ -239,6 +240,18 @@ export class DispatchSmartContract @state(Field) public tokenBridgeCount = State(); + public async deployAndInitialize( + args: DeployArgs | undefined, + permissions: Permissions, + settlementContract: PublicKey + ): Promise { + await super.deploy(args); + + this.self.account.permissions.set(permissions); + + this.initializeBase(settlementContract); + } + @method public async enableTokenDeposits( tokenId: Field, @@ -263,11 +276,6 @@ export class DispatchSmartContract ); } - @method - public async initialize(settlementContract: PublicKey) { - return this.initializeBase(settlementContract); - } - @method public async deposit( amount: UInt64, diff --git a/packages/protocol/src/settlement/contracts/SettlementSmartContract.ts b/packages/protocol/src/settlement/contracts/SettlementSmartContract.ts index 7dc375d2f..06ee0ce68 100644 --- a/packages/protocol/src/settlement/contracts/SettlementSmartContract.ts +++ b/packages/protocol/src/settlement/contracts/SettlementSmartContract.ts @@ -18,13 +18,13 @@ import { UInt32, AccountUpdateForest, TokenContract, - PrivateKey, VerificationKey, Permissions, Struct, Provable, TokenId, DynamicProof, + DeployArgs, } from "o1js"; import { NetworkState } from "../../model/network/NetworkState"; @@ -65,12 +65,13 @@ export class TokenMapping extends Struct({ export interface SettlementContractType { authorizationField: State; - initialize: ( + deployAndInitialize: ( + args: DeployArgs | undefined, + permissions: Permissions, sequencer: PublicKey, - dispatchContract: PublicKey, - bridgeContract: PublicKey, - contractKey: PrivateKey + dispatchContract: PublicKey ) => Promise; + assertStateRoot: (root: Field) => AccountUpdate; settle: ( blockProof: DynamicBlockProof, @@ -245,35 +246,13 @@ export abstract class SettlementSmartContractBase extends TokenContract { protected async initializeBase( sequencer: PublicKey, - dispatchContract: PublicKey, - bridgeContract: PublicKey, - contractKey: PrivateKey + dispatchContract: PublicKey ) { - this.sequencerKey.getAndRequireEquals().assertEquals(Field(0)); - this.stateRoot.getAndRequireEquals().assertEquals(Field(0)); - this.blockHashRoot.getAndRequireEquals().assertEquals(Field(0)); - this.networkStateHash.getAndRequireEquals().assertEquals(Field(0)); - this.dispatchContractAddressX.getAndRequireEquals().assertEquals(Field(0)); - this.sequencerKey.set(sequencer.x); this.stateRoot.set(LinkedMerkleTree.EMPTY_ROOT); this.blockHashRoot.set(Field(BlockHashMerkleTree.EMPTY_ROOT)); this.networkStateHash.set(NetworkState.empty().hash()); this.dispatchContractAddressX.set(dispatchContract.x); - - const { DispatchContract } = SettlementSmartContractBase.args; - const contractInstance = new DispatchContract(dispatchContract); - await contractInstance.initialize(this.address); - - // Deploy bridge contract for $Mina - await this.deployTokenBridge( - this.tokenId, - bridgeContract, - dispatchContract, - true - ); - - contractKey.toPublicKey().assertEquals(this.address); } protected async settleBase( @@ -449,23 +428,21 @@ export class SettlementSmartContract @state(Field) public authorizationField = State(); - @method async approveBase(forest: AccountUpdateForest) { - this.checkZeroBalanceChange(forest); + public async deployAndInitialize( + args: DeployArgs | undefined, + permissions: Permissions, + sequencer: PublicKey, + dispatchContract: PublicKey + ): Promise { + await super.deploy(args); + + this.self.account.permissions.set(permissions); + + await this.initializeBase(sequencer, dispatchContract); } - @method - public async initialize( - sequencer: PublicKey, - dispatchContract: PublicKey, - bridgeContract: PublicKey, - contractKey: PrivateKey - ) { - await this.initializeBase( - sequencer, - dispatchContract, - bridgeContract, - contractKey - ); + @method async approveBase(forest: AccountUpdateForest) { + this.checkZeroBalanceChange(forest); } @method diff --git a/packages/sequencer/src/settlement/SettlementModule.ts b/packages/sequencer/src/settlement/SettlementModule.ts index 2da841af2..9f70ffb89 100644 --- a/packages/sequencer/src/settlement/SettlementModule.ts +++ b/packages/sequencer/src/settlement/SettlementModule.ts @@ -16,6 +16,7 @@ import { PublicKey, Signature, TokenContract, + TokenId, Transaction, } from "o1js"; import { inject } from "tsyringe"; @@ -283,17 +284,25 @@ export class SettlementModule }, async () => { AccountUpdate.fundNewAccount(feepayer, 2); - await settlement.deploy({ - verificationKey: - verificationsKeys.SettlementSmartContract.verificationKey, - }); - settlement.account.permissions.set(permissions.settlementContract()); - - await dispatch.deploy({ - verificationKey: - verificationsKeys.DispatchSmartContract.verificationKey, - }); - dispatch.account.permissions.set(permissions.dispatchContract()); + + await dispatch.deployAndInitialize( + { + verificationKey: + verificationsKeys.DispatchSmartContract.verificationKey, + }, + permissions.dispatchContract(), + settlement.address + ); + + await settlement.deployAndInitialize( + { + verificationKey: + verificationsKeys.SettlementSmartContract.verificationKey, + }, + permissions.settlementContract(), + feepayerKey.toPublicKey(), + dispatchKey.toPublicKey() + ); } ).sign([feepayerKey, settlementKey, dispatchKey]); // Note: We can't use this.signTransaction on the above tx @@ -315,15 +324,15 @@ export class SettlementModule sender: feepayer, nonce: nonce + 1, fee: this.feeStrategy.getFee(), - memo: "Protokit settlement init", + memo: "Deploy MINA bridge", }, async () => { AccountUpdate.fundNewAccount(feepayer, 1); - await settlement.initialize( - feepayerKey.toPublicKey(), - dispatchKey.toPublicKey(), + // Deploy bridge contract for $Mina + await settlement.addTokenBridge( + TokenId.default, minaBridgeKey.toPublicKey(), - settlementKey + dispatchKey.toPublicKey() ); } );