@leofcoin/contracts 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/test.yml +33 -0
- package/.prettierrc +11 -11
- package/.size-log.json +115 -0
- package/LICENSE +20 -20
- package/README.md +27 -1
- package/exports/factory.d.ts +6 -3
- package/exports/factory.js +1 -1
- package/exports/name-service.js +1 -1
- package/exports/native-token.d.ts +1 -0
- package/exports/native-token.js +1 -1
- package/exports/power-token.js +1 -1
- package/exports/validators.d.ts +2 -5
- package/exports/validators.js +1 -1
- package/package.json +42 -43
- package/rollup.config.js +86 -86
- package/scripts/track-size.js +129 -0
- package/src/chat.ts +25 -25
- package/src/factory.ts +79 -73
- package/src/name-service.ts +93 -92
- package/src/native-token.ts +13 -7
- package/src/power-token.ts +7 -7
- package/src/validators.ts +148 -147
- package/test/factory.js +65 -66
- package/test/native-token.js +86 -96
- package/test/validators.js +119 -120
- package/tsconfig.json +14 -13
package/src/name-service.ts
CHANGED
|
@@ -1,92 +1,93 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { TokenReceiverState } from '@leofcoin/standards/token-receiver'
|
|
3
|
-
|
|
4
|
-
type registry = {
|
|
5
|
-
name?: {
|
|
6
|
-
address: address
|
|
7
|
-
owner: address
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface NameServiceState extends TokenReceiverState {
|
|
12
|
-
registry: registry
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default class NameService extends TokenReceiver {
|
|
16
|
-
/**
|
|
17
|
-
* string
|
|
18
|
-
*/
|
|
19
|
-
#name: string = 'LeofcoinNameService'
|
|
20
|
-
/**
|
|
21
|
-
* Object => string
|
|
22
|
-
*/
|
|
23
|
-
#registry: registry = {}
|
|
24
|
-
|
|
25
|
-
get name(): string {
|
|
26
|
-
return this.#name
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
get registry(): {} {
|
|
30
|
-
return { ...this.#registry }
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
get state(): NameServiceState {
|
|
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
|
-
this.#registry[name].owner
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
this.#registry[name].
|
|
91
|
-
|
|
92
|
-
}
|
|
1
|
+
import { TokenReceiver } from '@leofcoin/standards'
|
|
2
|
+
import { TokenReceiverState } from '@leofcoin/standards/token-receiver'
|
|
3
|
+
|
|
4
|
+
type registry = {
|
|
5
|
+
name?: {
|
|
6
|
+
address: address
|
|
7
|
+
owner: address
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface NameServiceState extends TokenReceiverState {
|
|
12
|
+
registry: registry
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default class NameService extends TokenReceiver {
|
|
16
|
+
/**
|
|
17
|
+
* string
|
|
18
|
+
*/
|
|
19
|
+
#name: string = 'LeofcoinNameService'
|
|
20
|
+
/**
|
|
21
|
+
* Object => string
|
|
22
|
+
*/
|
|
23
|
+
#registry: registry = {}
|
|
24
|
+
|
|
25
|
+
get name(): string {
|
|
26
|
+
return this.#name
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get registry(): {} {
|
|
30
|
+
return { ...this.#registry }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get state(): NameServiceState {
|
|
34
|
+
const baseState = super.state as TokenReceiverState
|
|
35
|
+
return {
|
|
36
|
+
...baseState,
|
|
37
|
+
registry: this.#registry
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// TODO: control with contract
|
|
42
|
+
constructor(
|
|
43
|
+
factoryAddress: address,
|
|
44
|
+
tokenToReceive: address,
|
|
45
|
+
validatorAddress: address,
|
|
46
|
+
tokenAmountToReceive: bigint,
|
|
47
|
+
state: NameServiceState
|
|
48
|
+
) {
|
|
49
|
+
super(tokenToReceive, tokenAmountToReceive, true, state as TokenReceiverState)
|
|
50
|
+
if (state) {
|
|
51
|
+
this.#registry = state.registry
|
|
52
|
+
} else {
|
|
53
|
+
this.#registry['LeofcoinContractFactory'] = {
|
|
54
|
+
owner: msg.sender,
|
|
55
|
+
address: msg.contract
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.#registry['LeofcoinToken'] = {
|
|
59
|
+
owner: msg.sender,
|
|
60
|
+
address: tokenToReceive
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this.#registry['LeofcoinValidators'] = {
|
|
64
|
+
owner: msg.sender,
|
|
65
|
+
address: validatorAddress
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async purchaseName(name: string | number, address: any) {
|
|
71
|
+
if (this.#registry[name]) throw new Error('name already registered')
|
|
72
|
+
await this._payTokenToReceive()
|
|
73
|
+
|
|
74
|
+
this.#registry[name] = {
|
|
75
|
+
owner: msg.sender,
|
|
76
|
+
address
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
lookup(name: string | number) {
|
|
81
|
+
return this.#registry[name]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
transferOwnership(name: string | number, to: any) {
|
|
85
|
+
if (msg.sender !== this.#registry[name].owner) throw new Error('not allowed')
|
|
86
|
+
this.#registry[name].owner = to
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
changeAddress(name: string | number, address: any) {
|
|
90
|
+
if (msg.sender !== this.#registry[name].owner) throw new Error('not allowed')
|
|
91
|
+
this.#registry[name].address = address
|
|
92
|
+
}
|
|
93
|
+
}
|
package/src/native-token.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import Token, { TokenState } from '@leofcoin/standards/token.js'
|
|
2
|
-
|
|
3
|
-
export default class Leofcoin extends Token {
|
|
4
|
-
constructor(state: TokenState) {
|
|
5
|
-
super('Leofcoin', 'LFC', 18, state)
|
|
6
|
-
}
|
|
7
|
-
|
|
1
|
+
import Token, { TokenState } from '@leofcoin/standards/token.js'
|
|
2
|
+
|
|
3
|
+
export default class Leofcoin extends Token {
|
|
4
|
+
constructor(state: TokenState) {
|
|
5
|
+
super('Leofcoin', 'LFC', 18, state)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
burn(from: address, amount: bigint) {
|
|
9
|
+
// Prevent balance underflow when burning
|
|
10
|
+
if (this.balanceOf(from) < amount) throw new Error('amount exceeds balance')
|
|
11
|
+
return super.burn(from, amount)
|
|
12
|
+
}
|
|
13
|
+
}
|
package/src/power-token.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import Token, { TokenState } from '@leofcoin/standards/token.js'
|
|
2
|
-
|
|
3
|
-
export default class Power extends Token {
|
|
4
|
-
constructor(state: TokenState) {
|
|
5
|
-
super('Power', 'PWR', 18, state)
|
|
6
|
-
}
|
|
7
|
-
}
|
|
1
|
+
import Token, { TokenState } from '@leofcoin/standards/token.js'
|
|
2
|
+
|
|
3
|
+
export default class Power extends Token {
|
|
4
|
+
constructor(state: TokenState) {
|
|
5
|
+
super('Power', 'PWR', 18, state)
|
|
6
|
+
}
|
|
7
|
+
}
|
package/src/validators.ts
CHANGED
|
@@ -1,147 +1,148 @@
|
|
|
1
|
-
import { lottery } from 'lucky-numbers'
|
|
2
|
-
import Roles
|
|
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
|
-
this.#
|
|
46
|
-
this.#
|
|
47
|
-
this.#
|
|
48
|
-
this.#
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.#
|
|
52
|
-
this.#
|
|
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
|
-
this
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.#
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
this.#
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
1
|
+
import { lottery } from 'lucky-numbers'
|
|
2
|
+
import Roles from '@leofcoin/standards/roles.js'
|
|
3
|
+
import type { RolesState } from '@leofcoin/standards/interfaces.js'
|
|
4
|
+
|
|
5
|
+
export declare interface ValidatorsState extends RolesState {
|
|
6
|
+
balances: { [address: string]: bigint }
|
|
7
|
+
minimumBalance: bigint
|
|
8
|
+
currency: address
|
|
9
|
+
validators: address[]
|
|
10
|
+
currentValidator: address
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default class Validators extends Roles {
|
|
14
|
+
/**
|
|
15
|
+
* string
|
|
16
|
+
*/
|
|
17
|
+
#name = 'LeofcoinValidators'
|
|
18
|
+
/**
|
|
19
|
+
* Object => string(address) => Object
|
|
20
|
+
*/
|
|
21
|
+
#validators: address[] = []
|
|
22
|
+
|
|
23
|
+
#currentValidator: address
|
|
24
|
+
|
|
25
|
+
#currency: address
|
|
26
|
+
|
|
27
|
+
#minimumBalance: bigint = BigInt(50_000)
|
|
28
|
+
|
|
29
|
+
#balances: { [address: address]: bigint } = {}
|
|
30
|
+
|
|
31
|
+
get state() {
|
|
32
|
+
return {
|
|
33
|
+
...super.state,
|
|
34
|
+
balances: this.#balances,
|
|
35
|
+
minimumBalance: this.#minimumBalance,
|
|
36
|
+
currency: this.#currency,
|
|
37
|
+
validators: this.#validators,
|
|
38
|
+
currentValidator: this.#currentValidator
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
constructor(tokenAddress: address, state: ValidatorsState) {
|
|
43
|
+
super(state)
|
|
44
|
+
if (state) {
|
|
45
|
+
this.#minimumBalance = BigInt(state.minimumBalance)
|
|
46
|
+
this.#currency = state.currency
|
|
47
|
+
this.#validators = state.validators
|
|
48
|
+
this.#balances = state.balances
|
|
49
|
+
this.#currentValidator = state.currentValidator
|
|
50
|
+
} else {
|
|
51
|
+
this.#currency = tokenAddress
|
|
52
|
+
this.#validators.push(msg.sender)
|
|
53
|
+
this.#currentValidator = msg.sender
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get currentValidator() {
|
|
58
|
+
return this.#currentValidator
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get name() {
|
|
62
|
+
return this.#name
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get currency() {
|
|
66
|
+
return this.#currency
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get validators() {
|
|
70
|
+
return this.#validators
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get totalValidators() {
|
|
74
|
+
return this.#validators.length
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get minimumBalance() {
|
|
78
|
+
return this.#minimumBalance
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
changeCurrency(currency) {
|
|
82
|
+
if (!this.hasRole(msg.sender, 'OWNER')) throw new Error('not an owner')
|
|
83
|
+
this.#currency = currency
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
has(validator) {
|
|
87
|
+
return this.#validators.includes(validator)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#isAllowed(address) {
|
|
91
|
+
if (msg.sender !== address && !this.hasRole(msg.sender, 'OWNER'))
|
|
92
|
+
throw new Error('sender is not the validator or owner')
|
|
93
|
+
return true
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async addValidator(validator: address) {
|
|
97
|
+
this.#isAllowed(validator)
|
|
98
|
+
if (this.has(validator)) throw new Error('validator already exists')
|
|
99
|
+
|
|
100
|
+
const balance = await msg.staticCall(this.currency, 'balanceOf', [validator])
|
|
101
|
+
|
|
102
|
+
if (this.minimumBalance > balance)
|
|
103
|
+
throw new Error(`balance to low! got: ${balance} need: ${this.#minimumBalance}`)
|
|
104
|
+
|
|
105
|
+
await msg.call(this.currency, 'transfer', [validator, msg.contract, this.#minimumBalance])
|
|
106
|
+
|
|
107
|
+
this.#balances[validator] = this.#minimumBalance
|
|
108
|
+
this.#validators.push(validator)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async removeValidator(validator) {
|
|
112
|
+
this.#isAllowed(validator)
|
|
113
|
+
if (!this.has(validator)) throw new Error('validator not found')
|
|
114
|
+
await msg.call(this.currency, 'transfer', [msg.contract, validator, this.#minimumBalance])
|
|
115
|
+
delete this.#balances[validator]
|
|
116
|
+
this.#validators.splice(this.#validators.indexOf(validator), 1)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
shuffleValidator() {
|
|
120
|
+
// todo introduce voting mechanism
|
|
121
|
+
// select amount of peers to vote & pass when 2/3 select the same peer
|
|
122
|
+
// this.vote
|
|
123
|
+
// todo only ids should be accessable
|
|
124
|
+
const _peers = state.peers
|
|
125
|
+
const peers = _peers
|
|
126
|
+
// only validators make a chance
|
|
127
|
+
.filter((peer) => this.#validators.includes(peer[0]))
|
|
128
|
+
// add up the bytes
|
|
129
|
+
.map((peer) => {
|
|
130
|
+
peer[1].totalBytes = peer[1].bw.up + peer[1].bw.down
|
|
131
|
+
return peer
|
|
132
|
+
})
|
|
133
|
+
.sort((a, b) => b[1].totalBytes - a[1].totalBytes)
|
|
134
|
+
// only return 128 best participating max
|
|
135
|
+
.splice(0, _peers.length > 128 ? 128 : _peers.length)
|
|
136
|
+
|
|
137
|
+
const luckyNumber = lottery(1, peers.length - 1)
|
|
138
|
+
|
|
139
|
+
let nextValidator = peers[luckyNumber[0]][0]
|
|
140
|
+
// redraw when the validator is the same
|
|
141
|
+
// but keep the net alive when only one validator is found
|
|
142
|
+
if (this.#currentValidator === nextValidator && peers.length !== 1) {
|
|
143
|
+
const luckyNumber = lottery(1, peers.length - 1)
|
|
144
|
+
nextValidator = peers[luckyNumber[0]][0]
|
|
145
|
+
}
|
|
146
|
+
this.#currentValidator = nextValidator
|
|
147
|
+
}
|
|
148
|
+
}
|
package/test/factory.js
CHANGED
|
@@ -1,66 +1,65 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (method === 'balanceOf') {
|
|
14
|
-
return BigInt(100000)
|
|
15
|
-
} else if (method === '
|
|
16
|
-
return true
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
call: async (currency, method, args) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (method === '
|
|
23
|
-
return
|
|
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
|
-
})
|
|
1
|
+
import { describe, it, beforeEach } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import Factory from './../exports/factory.js'
|
|
4
|
+
|
|
5
|
+
describe('Factory', () => {
|
|
6
|
+
let factory
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
global.msg = {
|
|
10
|
+
sender: '0xOwnerAddress',
|
|
11
|
+
contract: '0xContractAddress',
|
|
12
|
+
staticCall: async (currency, method, args) => {
|
|
13
|
+
if (method === 'balanceOf') {
|
|
14
|
+
return BigInt(100000)
|
|
15
|
+
} else if (method === 'creator') {
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
call: async (currency, method, args) => {
|
|
20
|
+
if (method === 'balanceOf') {
|
|
21
|
+
return BigInt(100000)
|
|
22
|
+
} else if (method === 'creator') {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
factory = new Factory('0xTokenAddress', BigInt(1000))
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('should throw an error if address is not a contract creator', async () => {
|
|
31
|
+
factory.isCreator = async () => false
|
|
32
|
+
await assert.rejects(async () => await factory.registerContract('0xContractAddress'), {
|
|
33
|
+
message: "You don't own that contract"
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('should throw an error if balance is too low', async () => {
|
|
38
|
+
global.msg.staticCall = async (currency, method, args) => {
|
|
39
|
+
if (method === 'balanceOf') {
|
|
40
|
+
return BigInt(100) // Balance too low
|
|
41
|
+
} else if (method === 'creator') {
|
|
42
|
+
return true
|
|
43
|
+
} else if (method === 'transfer') {
|
|
44
|
+
throw new Error('amount exceeds balance')
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
await assert.rejects(async () => await factory.registerContract('0xContractAddress'), {
|
|
48
|
+
message: 'amount exceeds balance'
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('should throw an error if contract is already registered', async () => {
|
|
53
|
+
await factory.registerContract('0xContractAddress')
|
|
54
|
+
await assert.rejects(async () => await factory.registerContract('0xContractAddress'), {
|
|
55
|
+
message: 'already registered'
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should successfully register a contract', async () => {
|
|
60
|
+
await factory.registerContract('0xContractAddress')
|
|
61
|
+
|
|
62
|
+
assert.equal(factory.totalContracts, BigInt(1))
|
|
63
|
+
assert.ok(factory.contracts.includes('0xContractAddress'))
|
|
64
|
+
})
|
|
65
|
+
})
|