Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pause tokens by default during deployment #85

Merged
merged 4 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 23 additions & 0 deletions FungibleToken.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ describe("token integration", async () => {
symbol: "tokB",
src: "",
decimals: UInt8.from(9),
startUnpaused: true,
})
})

Expand Down Expand Up @@ -130,6 +131,28 @@ describe("token integration", async () => {
const mintAmount = UInt64.from(1000)
const burnAmount = UInt64.from(100)

it("should not mint before calling resume()", async () => {
await rejects(() =>
Mina.transaction({
sender: sender,
fee: 1e8,
}, async () => {
AccountUpdate.fundNewAccount(sender, 1)
await tokenAContract.mint(sender, mintAmount)
})
)
})
it("should accept a call to resume()", async () => {
const tx = await Mina.transaction({
sender: sender,
fee: 1e8,
}, async () => {
await tokenAContract.resume()
})
tx.sign([sender.key, tokenAdmin.key])
await tx.prove()
await tx.send()
})
it("should mint for the sender account", async () => {
const initialBalance = (await tokenAContract.getBalanceOf(sender))
.toBigInt()
Expand Down
9 changes: 9 additions & 0 deletions FungibleToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ interface FungibleTokenDeployProps extends Exclude<DeployArgs, undefined> {
src: string
/** Number of decimals in a unit */
decimals: UInt8
/** Unless this is set to `true`, the tokens will start in paused mode,
* and will need to be explicitly resumed by calling the `resume()` method.
* You should only set this to `true` in atomic deploys. */
startUnpaused?: boolean
}

export class FungibleToken extends TokenContract {
Expand Down Expand Up @@ -75,6 +79,11 @@ export class FungibleToken extends TokenContract {
this.account.zkappUri.set(props.src)

this.actionState.set(Reducer.initialActionState)
if (props.startUnpaused) {
this.paused.set(Bool(false))
} else {
this.paused.set(Bool(true))
}
}

public async getAdminContract(): Promise<FungibleTokenAdminBase> {
Expand Down
5 changes: 5 additions & 0 deletions documentation/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ The `deploy` function takes as arguments
- A string pointing to the source code of the contract -- when following the standard, this should
point to the source of the standard implementation on github
- A `UInt8` for the number of decimals
- An optional `boolean` to signify whether token transfers should be enabled immediately. Unless
this is supplied and set to `true`, the token contract will be in a paused state initially, and
the `resume()` will need to be called before tokens can be minted or transferred. This is safer if
you have a non-atomic deploy (i.e., if you do not have the admin contract deployed in the same
transaction as the token contract itself).

and initializes the state of the contract. Initially, the circulating supply is set to zero, as no
tokens have been created yet.
Expand Down
5 changes: 5 additions & 0 deletions examples/concurrent-transfer.eg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ const deployTx = await Mina.transaction({
symbol: "abc",
src: "https://github.com/MinaFoundation/mina-fungible-token/blob/main/examples/e2e.eg.ts",
decimals: UInt8.from(9),
// We can set `startUnpaused` to true here, because we are doing an atomic deployment
// If you are not deploying the admin and token contracts in the same transaction,
// it is safer to start the tokens paused, and resume them only after verifying that
// the admin contract has been deployed
startUnpaused: true,
})
})
await deployTx.prove()
Expand Down
7 changes: 6 additions & 1 deletion examples/e2e.eg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Mina.setActiveInstance(localChain)

const fee = 1e8

const [deployer, owner, alexa, billy] = Mina.TestPublicKey.random(4)
const [deployer, owner, alexa, billy] = localChain.testAccounts
const contract = PrivateKey.randomKeypair()
const admin = PrivateKey.randomKeypair()

Expand All @@ -29,6 +29,11 @@ const deployTx = await Mina.transaction({
symbol: "abc",
src: "https://github.com/MinaFoundation/mina-fungible-token/blob/main/examples/e2e.eg.ts",
decimals: UInt8.from(9),
// We can set `startUnpaused` to true here, because we are doing an atomic deployment
// If you are not deploying the admin and token contracts in the same transaction,
// it is safer to start the tokens paused, and resume them only after verifying that
// the admin contract has been deployed
startUnpaused: true,
})
})
await deployTx.prove()
Expand Down
7 changes: 6 additions & 1 deletion examples/escrow.eg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Mina.setActiveInstance(localChain)

const fee = 1e8

const [deployer, owner, alexa, billy, jackie] = Mina.TestPublicKey.random(5)
const [deployer, owner, alexa, billy, jackie] = localChain.testAccounts
const tokenContract = PrivateKey.randomKeypair()
const escrowContract = PrivateKey.randomKeypair()
const admin = PrivateKey.randomKeypair()
Expand Down Expand Up @@ -84,6 +84,11 @@ const deployTokenTx = await Mina.transaction({
symbol: "abc",
src: "https://github.com/MinaFoundation/mina-fungible-token/blob/main/examples/escrow.eg.ts",
decimals: UInt8.from(9),
// We can set `startUnpaused` to true here, because we are doing an atomic deployment
// If you are not deploying the admin and token contracts in the same transaction,
// it is safer to start the tokens paused, and resume them only after verifying that
// the admin contract has been deployed
startUnpaused: true,
})
})
await deployTokenTx.prove()
Expand Down