Skip to content

Commit

Permalink
Change the way that the admin contract is customised.
Browse files Browse the repository at this point in the history
Using inheritance to change which constructor is used does not work. Instead, we are using a
`static` field, which can be set without changing the class.
  • Loading branch information
kantp committed May 7, 2024
1 parent e5fcd3a commit 8ea2b7a
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 22 deletions.
37 changes: 16 additions & 21 deletions FungibleToken.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ describe("token integration", () => {
let tokenA: TestPublicKey
let tokenAContract: FungibleToken
let tokenBAdmin: TestPublicKey
let tokenBAdminContract: TokenAdminB
let tokenBAdminContract: CustomTokenAdmin
let tokenB: TestPublicKey
let tokenBContract: FungibleTokenB
let tokenBContract: FungibleToken
let thirdPartyA: TestPublicKey
let thirdPartyAContract: ThirdParty
let thirdPartyB: TestPublicKey
Expand All @@ -62,9 +62,9 @@ describe("token integration", () => {
tokenAContract = new FungibleToken(tokenA)

tokenBAdmin = newTestPublicKey()
tokenBAdminContract = new TokenAdminB(tokenBAdmin)
tokenBAdminContract = new CustomTokenAdmin(tokenBAdmin)
tokenB = newTestPublicKey()
tokenBContract = new FungibleTokenB(tokenB)
tokenBContract = new FungibleToken(tokenB)

thirdPartyA = newTestPublicKey()
thirdPartyAContract = new ThirdParty(thirdPartyA)
Expand All @@ -76,8 +76,7 @@ describe("token integration", () => {
await FungibleToken.compile()
await ThirdParty.compile()
await FungibleTokenAdmin.compile()
await FungibleTokenB.compile()
await TokenAdminB.compile()
await CustomTokenAdmin.compile()
}
})

Expand Down Expand Up @@ -493,6 +492,7 @@ describe("token integration", () => {
const sendAmount = UInt64.from(100)

it("should mint with a custom admin contract", async () => {
FungibleToken.adminContract = CustomTokenAdmin
const initialBalance = (await tokenBContract.getBalanceOf(sender))
.toBigInt()

Expand All @@ -512,21 +512,21 @@ describe("token integration", () => {
(await tokenBContract.getBalanceOf(sender)).toBigInt(),
initialBalance + mintAmount.toBigInt(),
)
FungibleToken.adminContract = FungibleTokenAdmin
})

it("should send tokens without having the custom admin contract", async () => {
const vanillaContract = new FungibleToken(tokenB)
const initialBalanceSender = (await vanillaContract.getBalanceOf(sender))
const initialBalanceSender = (await tokenBContract.getBalanceOf(sender))
.toBigInt()
const initialBalanceReceiver = (await vanillaContract.getBalanceOf(receiver))
const initialBalanceReceiver = (await tokenBContract.getBalanceOf(receiver))
.toBigInt()

const tx = await Mina.transaction({
sender: sender,
fee: 1e8,
}, async () => {
AccountUpdate.fundNewAccount(sender, 1)
await vanillaContract.transfer(
await tokenBContract.transfer(
sender,
receiver,
sendAmount,
Expand All @@ -538,16 +538,17 @@ describe("token integration", () => {
await tx.send()

equal(
(await vanillaContract.getBalanceOf(sender)).toBigInt(),
(await tokenBContract.getBalanceOf(sender)).toBigInt(),
initialBalanceSender - sendAmount.toBigInt(),
)
equal(
(await vanillaContract.getBalanceOf(receiver)).toBigInt(),
(await tokenBContract.getBalanceOf(receiver)).toBigInt(),
initialBalanceReceiver + sendAmount.toBigInt(),
)
})

it("should not allow changing the total supply for token B", async () => {
FungibleToken.adminContract = CustomTokenAdmin
await rejects(async () =>
await Mina.transaction({
sender: sender,
Expand All @@ -556,14 +557,14 @@ describe("token integration", () => {
await tokenBContract.setSupply(mintAmount)
})
)
FungibleToken.adminContract = FungibleTokenAdmin
})
it("should not allow changing supply using the vanilla admin contract", async () => {
const vanillaContract = new FungibleToken(tokenB)
const tx = await Mina.transaction({
sender: sender,
fee: 1e8,
}, async () => {
await vanillaContract.setSupply(mintAmount)
await tokenBContract.setSupply(mintAmount)
})
tx.sign([tokenBAdmin.key])
await tx.prove()
Expand All @@ -573,7 +574,7 @@ describe("token integration", () => {
})

/** This is a faucet style admin contract, where anyone can mint */
class TokenAdminB extends SmartContract implements FungibleTokenAdminBase {
class CustomTokenAdmin extends SmartContract implements FungibleTokenAdminBase {
@state(PublicKey)
private adminPublicKey = State<PublicKey>()

Expand Down Expand Up @@ -604,12 +605,6 @@ class TokenAdminB extends SmartContract implements FungibleTokenAdminBase {
}
}

class FungibleTokenB extends FungibleToken {
public getAdminContract(): FungibleTokenAdminBase {
return (new TokenAdminB(this.admin.getAndRequireEquals()))
}
}

export default class ThirdParty extends SmartContract {
@state(PublicKey)
ownerAddress = State<PublicKey>()
Expand Down
7 changes: 6 additions & 1 deletion FungibleToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ export class FungibleToken extends TokenContract implements FungibleTokenLike {
@state(UInt64)
private circulating = State<UInt64>()

// This defines the type of the contract that is used to control access to administrative actions.
// If you want to have a custom contract, overwrite this by setting FungibleToken.adminContract to
// your own implementation of FungibleTokenAdminBase.
static adminContract: new(...args: any) => FungibleTokenAdminBase = FungibleTokenAdmin

readonly events = {
SetAdmin: PublicKey,
Mint: MintEvent,
Expand All @@ -54,7 +59,7 @@ export class FungibleToken extends TokenContract implements FungibleTokenLike {
}

public getAdminContract(): FungibleTokenAdminBase {
return (new FungibleTokenAdmin(this.admin.getAndRequireEquals()))
return (new FungibleToken.adminContract(this.admin.getAndRequireEquals()))
}

@method
Expand Down

0 comments on commit 8ea2b7a

Please sign in to comment.