-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathFungibleTokenAdmin.ts
99 lines (88 loc) · 2.88 KB
/
FungibleTokenAdmin.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import {
AccountUpdate,
assert,
Bool,
DeployArgs,
method,
Permissions,
Provable,
PublicKey,
SmartContract,
State,
state,
VerificationKey,
} from "o1js"
export type FungibleTokenAdminBase = SmartContract & {
canMint(accountUpdate: AccountUpdate): Promise<Bool>
canChangeAdmin(admin: PublicKey): Promise<Bool>
canPause(): Promise<Bool>
canResume(): Promise<Bool>
canChangeVerificationKey(vk: VerificationKey): Promise<Bool>
}
export interface FungibleTokenAdminDeployProps extends Exclude<DeployArgs, undefined> {
adminPublicKey: PublicKey
}
/** A contract that grants permissions for administrative actions on a token.
*
* We separate this out into a dedicated contract. That way, when issuing a token, a user can
* specify their own rules for administrative actions, without changing the token contract itself.
*
* The advantage is that third party applications that only use the token in a non-privileged way
* can integrate against the unchanged token contract.
*/
export class FungibleTokenAdmin extends SmartContract implements FungibleTokenAdminBase {
@state(PublicKey)
private adminPublicKey = State<PublicKey>()
async deploy(props: FungibleTokenAdminDeployProps) {
await super.deploy(props)
this.adminPublicKey.set(props.adminPublicKey)
this.account.permissions.set({
...Permissions.default(),
setVerificationKey: Permissions.VerificationKey.impossibleDuringCurrentVersion(),
setPermissions: Permissions.impossible(),
})
}
/** Update the verification key.
* Note that because we have set the permissions for setting the verification key to `impossibleDuringCurrentVersion()`, this will only be possible in case of a protocol update that requires an update.
*/
@method
async updateVerificationKey(vk: VerificationKey) {
this.account.verificationKey.set(vk)
}
private async ensureAdminSignature() {
const admin = await Provable.witnessAsync(PublicKey, async () => {
let pk = await this.adminPublicKey.fetch()
assert(pk !== undefined, "could not fetch admin public key")
return pk
})
this.adminPublicKey.requireEquals(admin)
return AccountUpdate.createSigned(admin)
}
@method.returns(Bool)
public async canMint(_accountUpdate: AccountUpdate) {
await this.ensureAdminSignature()
return Bool(true)
}
@method.returns(Bool)
public async canChangeAdmin(_admin: PublicKey) {
await this.ensureAdminSignature()
return Bool(true)
}
@method.returns(Bool)
public async canPause(): Promise<Bool> {
await this.ensureAdminSignature()
return Bool(true)
}
@method.returns(Bool)
public async canResume(): Promise<Bool> {
await this.ensureAdminSignature()
return Bool(true)
}
@method.returns(Bool)
public async canChangeVerificationKey(
_vk: VerificationKey,
): Promise<Bool> {
await this.ensureAdminSignature()
return Bool(true)
}
}