Skip to content

Commit 2809915

Browse files
committed
feat: Add wrapped ICX token
1 parent 5a059c6 commit 2809915

6 files changed

Lines changed: 464 additions & 0 deletions

File tree

score-lib/src/main/java/network/balanced/score/lib/utils/Names.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class Names {
4545
public final static String BURNER = "Balanced-ICON Burner";
4646
public final static String SAVINGS = "Balanced Savings";
4747
public final static String TRICKLER = "Balanced Trickler";
48+
public final static String WICX = "Wrapped ICX";
4849

4950
public final static String SPOKE_ASSET_MANAGER = "Balanced Spoke Asset Manager";
5051
public final static String SPOKE_XCALL_MANAGER = "Balanced Spoke XCall Manager";

score-lib/src/main/java/network/balanced/score/lib/utils/Versions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public class Versions {
4444
public final static String BURNER = "v1.0.0";
4545
public final static String SAVINGS = "v1.0.0";
4646
public final static String TRICKLER = "v1.0.0";
47+
public final static String WICX = "v1.0.1";
4748

4849
public final static String SPOKE_ASSET_MANAGER = "v1.0.2";
4950
public final static String SPOKE_XCALL_MANAGER = "v1.0.1";

token-contracts/WICX/build.gradle

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) 2022-2022 Balanced.network.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import network.balanced.score.dependencies.*
18+
19+
plugins {
20+
id 'java'
21+
}
22+
23+
version '1.0.0'
24+
25+
repositories {
26+
mavenCentral()
27+
}
28+
29+
dependencies {
30+
compileOnly Dependencies.javaeeApi
31+
implementation project(':score-lib')
32+
33+
testImplementation Dependencies.javaeeUnitTest
34+
testImplementation Dependencies.junitJupiter
35+
testRuntimeOnly Dependencies.junitJupiterEngine
36+
testImplementation project(':test-lib')
37+
testImplementation Dependencies.mockitoCore
38+
testImplementation Dependencies.mockitoInline
39+
}
40+
41+
deployJar {
42+
endpoints {
43+
sejong {
44+
uri = 'https://sejong.net.solidwallet.io/api/v3'
45+
nid = 0x53
46+
}
47+
berlin {
48+
uri = 'https://berlin.net.solidwallet.io/api/v3'
49+
nid = 0x7
50+
}
51+
lisbon {
52+
uri = 'https://lisbon.net.solidwallet.io/api/v3'
53+
nid = 0x2
54+
}
55+
local {
56+
uri = 'http://localhost:9082/api/v3'
57+
nid = 0x3
58+
}
59+
mainnet {
60+
uri = 'https://ctz.solidwallet.io/api/v3'
61+
nid = 0x1
62+
to = "cx3975b43d260fb8ec802cef6e60c2f4d07486f11d"
63+
}
64+
}
65+
keystore = rootProject.hasProperty('keystoreName') ? "$keystoreName" : ''
66+
password = rootProject.hasProperty('keystorePass') ? "$keystorePass" : ''
67+
parameters {
68+
arg("_governance", Addresses.mainnet.governance)
69+
}
70+
}
71+
72+
test {
73+
useJUnitPlatform()
74+
finalizedBy jacocoTestReport
75+
}
76+
77+
jacocoTestReport {
78+
dependsOn test
79+
reports {
80+
xml.required = true
81+
csv.required = false
82+
html.outputLocation = layout.buildDirectory.dir('jacocoHtml')
83+
}
84+
}
85+
optimizedJar {
86+
mainClassName = 'network.balanced.score.tokens.wicx.WICX'
87+
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
88+
from {
89+
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
90+
}
91+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* Copyright (c) 2022-2022 Balanced.network.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package network.balanced.score.tokens.wicx;
18+
19+
import network.balanced.score.lib.interfaces.tokens.IRC2;
20+
import score.Address;
21+
import score.Context;
22+
import score.DictDB;
23+
import score.VarDB;
24+
import score.annotation.EventLog;
25+
import score.annotation.External;
26+
import score.annotation.Optional;
27+
import score.annotation.Payable;
28+
29+
import java.math.BigInteger;
30+
31+
public class PayableIRC2Base implements IRC2 {
32+
33+
private final static String NAME = "name";
34+
private final static String SYMBOL = "symbol";
35+
private final static String DECIMALS = "decimals";
36+
private final static String TOTAL_SUPPLY = "total_supply";
37+
private final static String BALANCES = "balances";
38+
39+
static final Address ZERO_ADDRESS = new Address(new byte[Address.LENGTH]);
40+
41+
private final VarDB<String> name = Context.newVarDB(NAME, String.class);
42+
private final VarDB<String> symbol = Context.newVarDB(SYMBOL, String.class);
43+
private final VarDB<BigInteger> decimals = Context.newVarDB(DECIMALS, BigInteger.class);
44+
private final VarDB<BigInteger> totalSupply = Context.newVarDB(TOTAL_SUPPLY, BigInteger.class);
45+
protected final DictDB<Address, BigInteger> balances = Context.newDictDB(BALANCES, BigInteger.class);
46+
47+
protected PayableIRC2Base(String _tokenName, String _symbolName, @Optional BigInteger _decimals) {
48+
if (this.name.get() == null) {
49+
_decimals = _decimals == null ? BigInteger.valueOf(18L) : _decimals;
50+
Context.require(_decimals.compareTo(BigInteger.ZERO) >= 0, "Decimals cannot be less than zero");
51+
52+
this.name.set(ensureNotEmpty(_tokenName));
53+
this.symbol.set(ensureNotEmpty(_symbolName));
54+
this.decimals.set(_decimals);
55+
}
56+
}
57+
58+
@EventLog(indexed = 3)
59+
public void Transfer(Address _from, Address _to, BigInteger _value, byte[] _data) {
60+
}
61+
62+
private String ensureNotEmpty(String str) {
63+
Context.require(str != null && !str.trim().isEmpty(), "str is null or empty");
64+
assert str != null;
65+
return str.trim();
66+
}
67+
68+
@External(readonly = true)
69+
public String name() {
70+
return name.get();
71+
}
72+
73+
@External(readonly = true)
74+
public String symbol() {
75+
return symbol.get();
76+
}
77+
78+
@External(readonly = true)
79+
public BigInteger decimals() {
80+
return decimals.get();
81+
}
82+
83+
@External(readonly = true)
84+
public BigInteger totalSupply() {
85+
return totalSupply.getOrDefault(BigInteger.ZERO);
86+
}
87+
88+
@External(readonly = true)
89+
public BigInteger balanceOf(Address _owner) {
90+
return balances.getOrDefault(_owner, BigInteger.ZERO);
91+
}
92+
93+
@External
94+
@Payable
95+
public void transfer(Address _to, BigInteger _value, @Optional byte[] _data) {
96+
transfer(Context.getCaller(), _to, _value, _data);
97+
}
98+
99+
protected void transfer(Address _from, Address _to, BigInteger _value, byte[] _data) {
100+
Context.require(_value.compareTo(BigInteger.ZERO) >= 0, this.name.get() + ": _value needs to be positive");
101+
Context.require(balanceOf(_from).compareTo(_value) >= 0, this.name.get() + ": Insufficient balance");
102+
103+
this.balances.set(_from, balanceOf(_from).subtract(_value));
104+
this.balances.set(_to, balanceOf(_to).add(_value));
105+
106+
byte[] dataBytes = (_data == null) ? "None".getBytes() : _data;
107+
Transfer(_from, _to, _value, dataBytes);
108+
109+
if (_to.isContract()) {
110+
Context.call(_to, "tokenFallback", _from, _value, dataBytes);
111+
}
112+
}
113+
114+
protected void mint(Address owner, BigInteger amount) {
115+
Context.require(!ZERO_ADDRESS.equals(owner), this.name.get() + ": Owner address cannot be zero address");
116+
Context.require(amount.compareTo(BigInteger.ZERO) >= 0, this.name.get() + ": Amount needs to be positive");
117+
118+
totalSupply.set(totalSupply().add(amount));
119+
balances.set(owner, balanceOf(owner).add(amount));
120+
Transfer(ZERO_ADDRESS, owner, amount, "mint".getBytes());
121+
}
122+
123+
protected void burn(Address owner, BigInteger amount) {
124+
Context.require(!ZERO_ADDRESS.equals(owner), this.name.get() + ": Owner address cannot be zero address");
125+
Context.require(amount.compareTo(BigInteger.ZERO) >= 0, this.name.get() + ": Amount needs to be positive");
126+
Context.require(balanceOf(owner).compareTo(amount) >= 0, this.name.get() + ": Insufficient Balance");
127+
128+
balances.set(owner, balanceOf(owner).subtract(amount));
129+
totalSupply.set(totalSupply().subtract(amount));
130+
Transfer(owner, ZERO_ADDRESS, amount, "burn".getBytes());
131+
}
132+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright (c) 2022-2023 Balanced.network.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package network.balanced.score.tokens.wicx;
18+
19+
import network.balanced.score.lib.utils.Names;
20+
import network.balanced.score.lib.utils.Versions;
21+
import network.balanced.score.lib.utils.BalancedAddressManager;
22+
import score.Address;
23+
import score.Context;
24+
import score.VarDB;
25+
import score.annotation.External;
26+
import score.annotation.Optional;
27+
import score.annotation.Payable;
28+
29+
import java.math.BigInteger;
30+
31+
public class WICX extends PayableIRC2Base {
32+
33+
private static final String TOKEN_NAME = Names.WICX;
34+
private static final String SYMBOL_NAME = "wICX";
35+
private static final BigInteger DECIMALS = BigInteger.valueOf(18);
36+
private static final String VERSION = "version";
37+
38+
private final VarDB<String> currentVersion = Context.newVarDB(VERSION, String.class);
39+
40+
public WICX(Address _governance) {
41+
super(TOKEN_NAME, SYMBOL_NAME, DECIMALS);
42+
if (BalancedAddressManager.getAddressByName(Names.GOVERNANCE) == null) {
43+
BalancedAddressManager.setGovernance(_governance);
44+
}
45+
if (currentVersion.getOrDefault("").equals(Versions.WICX)) {
46+
Context.revert("Can't Update same version of code");
47+
}
48+
currentVersion.set(Versions.WICX);
49+
}
50+
51+
@External(readonly = true)
52+
public String version() {
53+
return currentVersion.getOrDefault("");
54+
}
55+
56+
@Override
57+
@Payable
58+
@External
59+
public void transfer(Address _to, BigInteger _value, @Optional byte[] _data) {
60+
Address from = Context.getCaller();
61+
BigInteger deposit = getICXDeposit();
62+
if (deposit.compareTo(BigInteger.ZERO) > 0) {
63+
mint(from, deposit);
64+
}
65+
super.transfer(_to, _value, _data);
66+
67+
if (!_to.isContract()) {
68+
burn(_to, _value);
69+
Context.transfer(_to, _value);
70+
}
71+
}
72+
73+
@External
74+
public void unwrap(BigInteger amount) {
75+
Address from = Context.getCaller();
76+
burn(from, amount);
77+
Context.transfer(from, amount);
78+
}
79+
80+
@Payable
81+
public void fallback() {
82+
Address from = Context.getCaller();
83+
BigInteger deposit = getICXDeposit();
84+
if (deposit.compareTo(BigInteger.ZERO) > 0) {
85+
mint(from, deposit);
86+
}
87+
}
88+
89+
BigInteger getICXDeposit() {
90+
return getICXDeposit();
91+
}
92+
93+
}

0 commit comments

Comments
 (0)