Smart Contract Details

Open on Dero Explorer
Internal ID:
108
Block:
Timestamp:
2022-07-30 00:48:48 UTC (3.0 years ago)
Creator:
test.keystore (+2 more) (1366966)
Raw Data:
[{"name":"SC_ACTION","datatype":"U","value":1},{"name":"SC_CODE","datatype":"S","value":"\n//    _____  _____ _______ _______ _  _  _ _______  _____ \n//   |_____]   |   |______ |______ |  |  | |_____| |_____]\n//   |       __|__ |______ ______| |__|__| |     | |      \n//\n//   Swap contract\n\nFunction Initialize(asset1 String, asset2 String, symbol String, name String, fee Uint64) Uint64\n\t10 IF EXISTS(\"version\") THEN GOTO 1100\n\t20 STORE(\"version\", GetVer())\n\t30 STORE(\"o:\" + HEX(SIGNER()), 0)\n\t40 STORE(\"ol:0\", HEX(SIGNER()))\n\t50 STORE(\"numTrustees\", 1)\n\t60 STORE(\"quorum\", 1)\n\t70 STORE(\"asset1\", HEXDECODE(asset1))\n\t80 STORE(\"asset2\", HEXDECODE(asset2))\n\t90 STORE(\"symbol\", symbol)\n\t100 STORE(\"decimals\", 0)\n\t110 STORE(\"name\", name)\n\t120 STORE(\"fee\", fee)\n\t130 STORE(\"val1\", 0)\n\t140 STORE(\"val2\", 0)\n\t150 STORE(\"sharesOutstanding\", 0)\n\t160 STORE(\"adds\", 0)\n\t170 STORE(\"rems\", 0)\n\t180 STORE(\"swaps\", 0)\n\n\t1000 RETURN 0\n\t1100 RETURN 100\nEnd Function\n\n\tFunction GetVer() String\n\t10 return \"2.010\"\nEnd Function\n\n\t// lossless (a * b ) / c\n\t// (cause there ain't no Uint256)\nFunction multDiv(a Uint64, b Uint64, c Uint64) Uint64\n\t10 DIM base, maxdiv AS Uint64\n\t20 LET base = 4294967296\t// (1\u003c\u003c32)\n\t30 LET maxdiv = (base-1)*base + (base-1)\n\n\t50 DIM res AS Uint64\n\t60 LET res = (a/c) * b + (a%c) * (b/c)\n\t70 LET a = a % c\n\t80 LET b = b % c\n\t90 IF (a == 0 || b == 0) THEN GOTO 1000\n\n\t100 IF (c \u003e= base) THEN GOTO 200\n\t110 LET res = res + (a*b/c)\n\t120 GOTO 1000\n\n\t200 DIM norm AS Uint64\n\t210 LET norm = maxdiv/c\n\t220 LET c = c * norm\n\t230 LET a = a * norm\n\n\t300 DIM ah, al, bh, bl, ch, cl AS Uint64\n\t310 LET ah = a / base\n\t320 LET al = a % base\n\t330 LET bh = b / base\n\t340 LET bl = b % base\n\t350 LET ch = c / base\n\t360 LET cl = c % base\n\n\t400 DIM p0, p1, p2 AS Uint64\n\t410 LET p0 = al*bl\n\t420 LET p1 = p0 / base + al*bh\n\t430 LET p0 = p0 % base\n\t440 LET p2 = p1 / base + ah*bh\n\t450 LET p1 = (p1 % base) + ah*bl\n\t460 LET p2 = p2 + p1 / base\n\t470 LET p1 = p1 % base\n\n\t500 DIM q0, q1, rhat AS Uint64\n\t510 LET p2 = p2 % c\n\t520 LET q1 = p2 / ch\n\t530 LET rhat = p2 % ch\n\n\t600 IF (q1 \u003c base \u0026\u0026 (rhat \u003e= base || q1*cl \u003c= rhat*base+p1)) THEN GOTO 700\n\t610 LET q1 = q1 - 1\n\t620 LET rhat = rhat + ch\n\t630 GOTO 600\n\n\t700 LET p1 = ((p2 % base) * base + p1) - q1 * cl\n\t710 LET p2 = (p2 / base * base + p1 / base) - q1 * ch\n\t720 LET p1 = (p1 % base) + (p2 % base) * base\n\t730 LET q0 = p1 / ch\n\t740 LET rhat = p1 % ch\n\n\t800 IF (q0 \u003c base \u0026\u0026 (rhat \u003e= base || q0*cl \u003c= rhat*base+p0)) THEN GOTO 900\n\t810 LET q0 = q0 - 1\n\t820 LET rhat = rhat + ch\n\t830 GOTO 800\n\n\t900 LET res = res + q0 + q1 * base\n\n\t1000 RETURN res\nEnd Function\n\nFunction AddLiquidity() Uint64 \n\t10 DIM in1, in2, val1, val2, inRatio, valRatio, sharesOutstanding, share AS Uint64\n\t20 DIM asset1, asset2 AS String\n\n\t30 LET asset1 = LOAD(\"asset1\")\n\t40 LET asset2 = LOAD(\"asset2\")\n\t50 LET val1 = LOAD(\"val1\")\n\t60 LET val2 = LOAD(\"val2\")\n\t70 LET sharesOutstanding = LOAD(\"sharesOutstanding\")\n\t80 LET in1 = ASSETVALUE(asset1)\n\t90 LET in2 = ASSETVALUE(asset2)\n\n\t100 IF in1 \u003c 1 || in2 \u003c 1 THEN GOTO 1110\n\t110 IF sharesOutstanding \u003e 0 THEN GOTO 130\n\t115 LET share = MAX(in1, in2)\n\t120 GOTO 300\n\n\t130 IF val2 \u003e val1 THEN GOTO 170\n\t140 LET valRatio = val1 / val2\n\t150 LET inRatio = in1 / in2\n\t160 GOTO 190\n\n\t170 LET valRatio = val2 / val1\n\t180 LET inRatio = in2 / in1\n\t190 IF valRatio != inRatio THEN GOTO 1120\n\n\t200 LET share = multDiv(sharesOutstanding, in1, val1)\n\n\t300 SEND_ASSET_TO_ADDRESS(SIGNER(), share, SCID())\n\t310 STORE(\"val1\", val1 + in1)\n\t320 STORE(\"val2\", val2 + in2)\n\t330 STORE(\"sharesOutstanding\", sharesOutstanding + share)\n\t340 STORE(\"adds\", LOAD(\"adds\") + 1)\n\n\t1000 RETURN 0\n\t1110 RETURN 110\n\t1120 RETURN 120\nEnd Function\n\nFunction RemoveLiquidity() Uint64\n\t10 DIM out1, out2, val1, val2, shares, sharesOutstanding AS Uint64\n\t20 DIM asset1, asset2 AS String\n\n\t30 LET val1 = LOAD(\"val1\")\n\t40 LET val2 = LOAD(\"val2\")\n\t50 LET shares = ASSETVALUE(SCID())\n\t60 LET sharesOutstanding = LOAD(\"sharesOutstanding\")\n\t70 LET asset1 = LOAD(\"asset1\")\n\t80 LET asset2 = LOAD(\"asset2\")\n\n\t90 IF sharesOutstanding \u003c 1 || shares \u003c 1 THEN GOTO 1130\n\t100 LET out1 = multDiv(val1, shares, sharesOutstanding)\n\t110 LET out2 = multDiv(val2, shares, sharesOutstanding)\n\n\t120 STORE(\"val1\", val1 - out1)\n\t130 STORE(\"val2\", val2 - out2)\n\t140 STORE(\"sharesOutstanding\", sharesOutstanding - shares)\n\t150 STORE(\"rems\", LOAD(\"rems\") + 1)\n\t160 SEND_ASSET_TO_ADDRESS(SIGNER(), out1, asset1)\n\t170 SEND_ASSET_TO_ADDRESS(SIGNER(), out2, asset2)\n\n\t1000 RETURN 0\n\t1100 RETURN 100\n\t1130 RETURN 130\nEnd Function\n\nFunction Swap() Uint64\n\t10 DIM in1, in2, out1, out2, val1, val2, fee AS Uint64\n\t20 DIM asset1, asset2 AS String\n\n\t30 LET asset1 = LOAD(\"asset1\")\n\t40 LET asset2 = LOAD(\"asset2\")\n\t50 LET in1 = ASSETVALUE(asset1)\n\t60 LET in2 = ASSETVALUE(asset2)\n\t70 LET val1 = LOAD(\"val1\")\n\t80 LET val2 = LOAD(\"val2\")\n\t90 LET fee = LOAD(\"fee\")\n\n\t100 IF in1 \u003e 0 \u0026\u0026 in2 \u003e 0 THEN GOTO 1140\n\t110 IF in1 \u003c 1 \u0026\u0026 in2 \u003c 1 THEN GOTO 1110\n\t120 IF in2 \u003e 0 THEN GOTO 300\n\n\t200 LET out2 = multDiv(in1, val2, (val1 + in1))\n\t210 LET out2 = multDiv(out2, (10000-fee), 10000)\n\t220 STORE(\"val1\", val1 + in1)\n\t230 STORE(\"val2\", val2 - out2)\n\t250 SEND_ASSET_TO_ADDRESS(SIGNER(), out2, asset2)\n\t260 GOTO 400\n\n\t300 LET out1 = multDiv(in2, val1, (val2 + in2))\n\t310 LET out1 = multDiv(out1, (10000-fee), 10000)\n\t320 STORE(\"val1\", val1 - out1)\n\t330 STORE(\"val2\", val2 + in2)\n\t350 SEND_ASSET_TO_ADDRESS(SIGNER(), out1, asset1)\n\n\t400 STORE(\"swaps\", LOAD(\"swaps\") + 1)\n\n\t1000 RETURN 0\n\t1100 RETURN 100\n\t1110 RETURN 110\n\t1140 RETURN 140\nEnd Function\n\nFunction VoteSetFee(fee Uint64) Uint64\n\t10 DIM trustee AS String\n\t20 LET trustee = \"o:\" + HEX(SIGNER())\n\t30 IF EXISTS(trustee) != 1 THEN GOTO 1100\n\t40 IF LOAD(\"fee\") == fee THEN GOTO 1260\n\n\t100 IF castVote(trustee, \"0\", ITOA(fee)) != 1 THEN GOTO 200\n\t110 DELETE(\"i:0\")\n\t120 STORE(\"fee\", fee)\n\n\t1000 RETURN 0\n\t1100 RETURN 100\n\t1260 RETURN 260\nEnd Function\n\nFunction VoteAddTrustee(new_trustee String) Uint64\n\t10 DIM trustee AS String\n\t20 LET trustee = \"o:\" + HEX(SIGNER())\n\t30 IF EXISTS(trustee) != 1 THEN GOTO 1100\n\t40 IF EXISTS(\"o:\" + new_trustee) THEN GOTO 1260\n\t50 IF STRLEN(new_trustee) != 64 THEN GOTO 1260\n\n\t100 IF castVote(trustee, \"1\", new_trustee) != 1 THEN GOTO 200\n\t110 DELETE(\"i:1\")\n\t120 DIM numTrustees AS Uint64\n\t130 LET numTrustees = LOAD(\"numTrustees\")\n\t140 STORE(\"ol:\" + numTrustees, new_trustee)\n\t150 STORE(\"o:\"+ new_trustee, numTrustees)\n\t160 STORE(\"numTrustees\", numTrustees + 1)\n\n\t200 RETURN 0\n\n\t1100 RETURN 100\n\t1260 RETURN 260\nEnd Function\n\nFunction VoteRemoveTrustee(old_trustee String) Uint64\n\t10 DIM trustee AS String\n\t20 DIM numTrustees AS Uint64\n\t30 LET trustee = \"o:\" + HEX(SIGNER())\n\t40 IF EXISTS(trustee) != 1 THEN GOTO 1100\n\t50 IF EXISTS(\"o:\" + old_trustee) != 1 THEN GOTO 1260\n\t60 LET numTrustees = LOAD(\"numTrustees\") - 1\n\t70 IF numTrustees == 0 THEN GOTO 1270\n\t80 IF numTrustees \u003e LOAD(\"quorum\") THEN GOTO 1280\n\n\t100 IF castVote(trustee, \"2\", old_trustee) != 1 THEN GOTO 300\n\t110 DELETE(\"i:2\")\n\n\t200 DIM keyToMove AS String\n\t210 DIM rowToReplace AS Uint64\n\t220 LET keyToMove = LOAD(\"ol:\" + numTrustees)\n\t230 LET rowToReplace = LOAD(\"o:\" + old_trustee)\n\t240 STORE(\"o:\" + keyToMove, rowToReplace)\n\t250 STORE(\"ol:\" + rowToReplace, keyToMove)\n\t260 DELETE(\"o:\" + old_trustee)\n\t270 DELETE(\"ol:\" + numTrustees)\n\t280 STORE(\"numTrustees\", numTrustees)\n\n\t300 RETURN 0\n\n\t1100 RETURN 100\n\t1260 RETURN 260\n\t1270 RETURN 270\n\t1290 RETURN 290\nEnd Function\n\nFunction VoteChangeQuorum(new_quorum Uint64) Uint64\n\t10 DIM trustee AS String\n\t20 LET trustee = \"o:\" + HEX(SIGNER())\n\t30 IF EXISTS(trustee) != 1 THEN GOTO 1100\n\t40 IF LOAD(\"quorum\") == new_quorum THEN GOTO 1260\n\t50 IF new_quorum \u003e LOAD(\"numTrustees\") THEN GOTO 1300\n\n\t100 IF castVote(trustee, \"3\", ITOA(new_quorum)) != 1 THEN GOTO 200\n\t110 DELETE(\"i:3\")\n\t120 STORE(\"quorum\", new_quorum)\n\n\t200 RETURN 0\n\n\t1100 RETURN 100\n\t1260 RETURN 260\n\t1300 RETURN 300\nEnd Function\n\nFunction VoteUpdateCode(code String) Uint64\n\t10 DIM trustee AS String\n\t20 LET trustee = \"o:\" + HEX(SIGNER())\n\t30 IF EXISTS(trustee) != 1 THEN GOTO 1100\n\n\t100 IF castVote(trustee, \"4\", sha256(code)) != 1 THEN GOTO 200\n\t110 DELETE(\"i:4\")\n\t120 UPDATE_SC_CODE(code)\n\n\t200 RETURN 0\n\n\t1100 RETURN 100\n\t1260 RETURN 260\nEnd Function\n\nFunction countVotes(tally Uint64) Uint64\n\t10 DIM votes, i AS Uint64\n\t20 LET votes = 0\n\t30 LET i = LOAD(\"numTrustees\")\n\n\t100 IF (tally \u0026 (1\u003c\u003ci)) \u003c 1 THEN GOTO 120\n\t110 LET votes = votes + 1\n\t120 LET i = i - 1\n\t130 IF i \u003c 1 THEN GOTO 1000\n\t140 GOTO 100\n\n\t1000 RETURN votes\nEnd Function\n\nFunction SHL(a Uint64, b Uint64) Uint64\n\t10 RETURN a \u003c\u003c b\nEnd Function\n\nFunction castVote(trustee String, key String, proposal String) Uint64\n\t10 DIM value, c, tally_str AS String\n\t20 DIM i, tally AS Uint64\n\t30 LET tally_str = \"0\"\n\t40 IF EXISTS(\"i:\" + key) != 1 THEN GOTO 200\n\t50 LET value = LOAD(\"i:\" + key)\n\t60 LET i = 0\n\n\t100 LET c = SUBSTR(value, i, 1)\n\t110 IF (c == \":\") THEN GOTO 200\n\t120 LET tally_str = tally_str + c\n\t130 LET i = i + 1\n\t140 GOTO 100\n\n\t200 LET tally = ATOI(tally_str)\n\t210 IF ((tally \u0026 1) == 1) THEN GOTO 1000\n\t220 IF SUBSTR(value, i+1, STRLEN(proposal)) == proposal THEN GOTO 300\n\t230 LET tally = 0\n\n\t300 LET tally = tally | SHL(1, LOAD(trustee) + 1)\n\t310 IF countVotes(tally) \u003c LOAD(\"quorum\") THEN GOTO 400\n\t320 LET tally = tally | 1\n\n\t400 STORE(\"i:\" + key, ITOA(tally) + \":\" + proposal)\n\t410 RETURN (tally \u0026 1)\n\n\t1000 RETURN 0\nEnd Function\n"},{"name":"asset1","datatype":"S","value":"0000000000000000000000000000000000000000000000000000000000000000"},{"name":"asset2","datatype":"S","value":"b0bb9c1c75fc0e84dd92ce03f0619d1b61737981f0bb796911ea31529a76358c"},{"name":"fee","datatype":"U","value":0},{"name":"name","datatype":"S","value":"Liquidity for swap pair DERO:DWBTC"},{"name":"symbol","datatype":"S","value":"DERO:DWBTC"}]
Code:

//    _____  _____ _______ _______ _  _  _ _______  _____ 
//   |_____]   |   |______ |______ |  |  | |_____| |_____]
//   |       __|__ |______ ______| |__|__| |     | |      
//
//   Swap contract

Function Initialize(asset1 String, asset2 String, symbol String, name String, fee Uint64) Uint64
	10 IF EXISTS("version") THEN GOTO 1100
	20 STORE("version", GetVer())
	30 STORE("o:" + HEX(SIGNER()), 0)
	40 STORE("ol:0", HEX(SIGNER()))
	50 STORE("numTrustees", 1)
	60 STORE("quorum", 1)
	70 STORE("asset1", HEXDECODE(asset1))
	80 STORE("asset2", HEXDECODE(asset2))
	90 STORE("symbol", symbol)
	100 STORE("decimals", 0)
	110 STORE("name", name)
	120 STORE("fee", fee)
	130 STORE("val1", 0)
	140 STORE("val2", 0)
	150 STORE("sharesOutstanding", 0)
	160 STORE("adds", 0)
	170 STORE("rems", 0)
	180 STORE("swaps", 0)

	1000 RETURN 0
	1100 RETURN 100
End Function

	Function GetVer() String
	10 return "2.010"
End Function

	// lossless (a * b ) / c
	// (cause there ain't no Uint256)
Function multDiv(a Uint64, b Uint64, c Uint64) Uint64
	10 DIM base, maxdiv AS Uint64
	20 LET base = 4294967296	// (1<<32)
	30 LET maxdiv = (base-1)*base + (base-1)

	50 DIM res AS Uint64
	60 LET res = (a/c) * b + (a%c) * (b/c)
	70 LET a = a % c
	80 LET b = b % c
	90 IF (a == 0 || b == 0) THEN GOTO 1000

	100 IF (c >= base) THEN GOTO 200
	110 LET res = res + (a*b/c)
	120 GOTO 1000

	200 DIM norm AS Uint64
	210 LET norm = maxdiv/c
	220 LET c = c * norm
	230 LET a = a * norm

	300 DIM ah, al, bh, bl, ch, cl AS Uint64
	310 LET ah = a / base
	320 LET al = a % base
	330 LET bh = b / base
	340 LET bl = b % base
	350 LET ch = c / base
	360 LET cl = c % base

	400 DIM p0, p1, p2 AS Uint64
	410 LET p0 = al*bl
	420 LET p1 = p0 / base + al*bh
	430 LET p0 = p0 % base
	440 LET p2 = p1 / base + ah*bh
	450 LET p1 = (p1 % base) + ah*bl
	460 LET p2 = p2 + p1 / base
	470 LET p1 = p1 % base

	500 DIM q0, q1, rhat AS Uint64
	510 LET p2 = p2 % c
	520 LET q1 = p2 / ch
	530 LET rhat = p2 % ch

	600 IF (q1 < base && (rhat >= base || q1*cl <= rhat*base+p1)) THEN GOTO 700
	610 LET q1 = q1 - 1
	620 LET rhat = rhat + ch
	630 GOTO 600

	700 LET p1 = ((p2 % base) * base + p1) - q1 * cl
	710 LET p2 = (p2 / base * base + p1 / base) - q1 * ch
	720 LET p1 = (p1 % base) + (p2 % base) * base
	730 LET q0 = p1 / ch
	740 LET rhat = p1 % ch

	800 IF (q0 < base && (rhat >= base || q0*cl <= rhat*base+p0)) THEN GOTO 900
	810 LET q0 = q0 - 1
	820 LET rhat = rhat + ch
	830 GOTO 800

	900 LET res = res + q0 + q1 * base

	1000 RETURN res
End Function

Function AddLiquidity() Uint64 
	10 DIM in1, in2, val1, val2, inRatio, valRatio, sharesOutstanding, share AS Uint64
	20 DIM asset1, asset2 AS String

	30 LET asset1 = LOAD("asset1")
	40 LET asset2 = LOAD("asset2")
	50 LET val1 = LOAD("val1")
	60 LET val2 = LOAD("val2")
	70 LET sharesOutstanding = LOAD("sharesOutstanding")
	80 LET in1 = ASSETVALUE(asset1)
	90 LET in2 = ASSETVALUE(asset2)

	100 IF in1 < 1 || in2 < 1 THEN GOTO 1110
	110 IF sharesOutstanding > 0 THEN GOTO 130
	115 LET share = MAX(in1, in2)
	120 GOTO 300

	130 IF val2 > val1 THEN GOTO 170
	140 LET valRatio = val1 / val2
	150 LET inRatio = in1 / in2
	160 GOTO 190

	170 LET valRatio = val2 / val1
	180 LET inRatio = in2 / in1
	190 IF valRatio != inRatio THEN GOTO 1120

	200 LET share = multDiv(sharesOutstanding, in1, val1)

	300 SEND_ASSET_TO_ADDRESS(SIGNER(), share, SCID())
	310 STORE("val1", val1 + in1)
	320 STORE("val2", val2 + in2)
	330 STORE("sharesOutstanding", sharesOutstanding + share)
	340 STORE("adds", LOAD("adds") + 1)

	1000 RETURN 0
	1110 RETURN 110
	1120 RETURN 120
End Function

Function RemoveLiquidity() Uint64
	10 DIM out1, out2, val1, val2, shares, sharesOutstanding AS Uint64
	20 DIM asset1, asset2 AS String

	30 LET val1 = LOAD("val1")
	40 LET val2 = LOAD("val2")
	50 LET shares = ASSETVALUE(SCID())
	60 LET sharesOutstanding = LOAD("sharesOutstanding")
	70 LET asset1 = LOAD("asset1")
	80 LET asset2 = LOAD("asset2")

	90 IF sharesOutstanding < 1 || shares < 1 THEN GOTO 1130
	100 LET out1 = multDiv(val1, shares, sharesOutstanding)
	110 LET out2 = multDiv(val2, shares, sharesOutstanding)

	120 STORE("val1", val1 - out1)
	130 STORE("val2", val2 - out2)
	140 STORE("sharesOutstanding", sharesOutstanding - shares)
	150 STORE("rems", LOAD("rems") + 1)
	160 SEND_ASSET_TO_ADDRESS(SIGNER(), out1, asset1)
	170 SEND_ASSET_TO_ADDRESS(SIGNER(), out2, asset2)

	1000 RETURN 0
	1100 RETURN 100
	1130 RETURN 130
End Function

Function Swap() Uint64
	10 DIM in1, in2, out1, out2, val1, val2, fee AS Uint64
	20 DIM asset1, asset2 AS String

	30 LET asset1 = LOAD("asset1")
	40 LET asset2 = LOAD("asset2")
	50 LET in1 = ASSETVALUE(asset1)
	60 LET in2 = ASSETVALUE(asset2)
	70 LET val1 = LOAD("val1")
	80 LET val2 = LOAD("val2")
	90 LET fee = LOAD("fee")

	100 IF in1 > 0 && in2 > 0 THEN GOTO 1140
	110 IF in1 < 1 && in2 < 1 THEN GOTO 1110
	120 IF in2 > 0 THEN GOTO 300

	200 LET out2 = multDiv(in1, val2, (val1 + in1))
	210 LET out2 = multDiv(out2, (10000-fee), 10000)
	220 STORE("val1", val1 + in1)
	230 STORE("val2", val2 - out2)
	250 SEND_ASSET_TO_ADDRESS(SIGNER(), out2, asset2)
	260 GOTO 400

	300 LET out1 = multDiv(in2, val1, (val2 + in2))
	310 LET out1 = multDiv(out1, (10000-fee), 10000)
	320 STORE("val1", val1 - out1)
	330 STORE("val2", val2 + in2)
	350 SEND_ASSET_TO_ADDRESS(SIGNER(), out1, asset1)

	400 STORE("swaps", LOAD("swaps") + 1)

	1000 RETURN 0
	1100 RETURN 100
	1110 RETURN 110
	1140 RETURN 140
End Function

Function VoteSetFee(fee Uint64) Uint64
	10 DIM trustee AS String
	20 LET trustee = "o:" + HEX(SIGNER())
	30 IF EXISTS(trustee) != 1 THEN GOTO 1100
	40 IF LOAD("fee") == fee THEN GOTO 1260

	100 IF castVote(trustee, "0", ITOA(fee)) != 1 THEN GOTO 200
	110 DELETE("i:0")
	120 STORE("fee", fee)

	1000 RETURN 0
	1100 RETURN 100
	1260 RETURN 260
End Function

Function VoteAddTrustee(new_trustee String) Uint64
	10 DIM trustee AS String
	20 LET trustee = "o:" + HEX(SIGNER())
	30 IF EXISTS(trustee) != 1 THEN GOTO 1100
	40 IF EXISTS("o:" + new_trustee) THEN GOTO 1260
	50 IF STRLEN(new_trustee) != 64 THEN GOTO 1260

	100 IF castVote(trustee, "1", new_trustee) != 1 THEN GOTO 200
	110 DELETE("i:1")
	120 DIM numTrustees AS Uint64
	130 LET numTrustees = LOAD("numTrustees")
	140 STORE("ol:" + numTrustees, new_trustee)
	150 STORE("o:"+ new_trustee, numTrustees)
	160 STORE("numTrustees", numTrustees + 1)

	200 RETURN 0

	1100 RETURN 100
	1260 RETURN 260
End Function

Function VoteRemoveTrustee(old_trustee String) Uint64
	10 DIM trustee AS String
	20 DIM numTrustees AS Uint64
	30 LET trustee = "o:" + HEX(SIGNER())
	40 IF EXISTS(trustee) != 1 THEN GOTO 1100
	50 IF EXISTS("o:" + old_trustee) != 1 THEN GOTO 1260
	60 LET numTrustees = LOAD("numTrustees") - 1
	70 IF numTrustees == 0 THEN GOTO 1270
	80 IF numTrustees > LOAD("quorum") THEN GOTO 1280

	100 IF castVote(trustee, "2", old_trustee) != 1 THEN GOTO 300
	110 DELETE("i:2")

	200 DIM keyToMove AS String
	210 DIM rowToReplace AS Uint64
	220 LET keyToMove = LOAD("ol:" + numTrustees)
	230 LET rowToReplace = LOAD("o:" + old_trustee)
	240 STORE("o:" + keyToMove, rowToReplace)
	250 STORE("ol:" + rowToReplace, keyToMove)
	260 DELETE("o:" + old_trustee)
	270 DELETE("ol:" + numTrustees)
	280 STORE("numTrustees", numTrustees)

	300 RETURN 0

	1100 RETURN 100
	1260 RETURN 260
	1270 RETURN 270
	1290 RETURN 290
End Function

Function VoteChangeQuorum(new_quorum Uint64) Uint64
	10 DIM trustee AS String
	20 LET trustee = "o:" + HEX(SIGNER())
	30 IF EXISTS(trustee) != 1 THEN GOTO 1100
	40 IF LOAD("quorum") == new_quorum THEN GOTO 1260
	50 IF new_quorum > LOAD("numTrustees") THEN GOTO 1300

	100 IF castVote(trustee, "3", ITOA(new_quorum)) != 1 THEN GOTO 200
	110 DELETE("i:3")
	120 STORE("quorum", new_quorum)

	200 RETURN 0

	1100 RETURN 100
	1260 RETURN 260
	1300 RETURN 300
End Function

Function VoteUpdateCode(code String) Uint64
	10 DIM trustee AS String
	20 LET trustee = "o:" + HEX(SIGNER())
	30 IF EXISTS(trustee) != 1 THEN GOTO 1100

	100 IF castVote(trustee, "4", sha256(code)) != 1 THEN GOTO 200
	110 DELETE("i:4")
	120 UPDATE_SC_CODE(code)

	200 RETURN 0

	1100 RETURN 100
	1260 RETURN 260
End Function

Function countVotes(tally Uint64) Uint64
	10 DIM votes, i AS Uint64
	20 LET votes = 0
	30 LET i = LOAD("numTrustees")

	100 IF (tally & (1<<i)) < 1 THEN GOTO 120
	110 LET votes = votes + 1
	120 LET i = i - 1
	130 IF i < 1 THEN GOTO 1000
	140 GOTO 100

	1000 RETURN votes
End Function

Function SHL(a Uint64, b Uint64) Uint64
	10 RETURN a << b
End Function

Function castVote(trustee String, key String, proposal String) Uint64
	10 DIM value, c, tally_str AS String
	20 DIM i, tally AS Uint64
	30 LET tally_str = "0"
	40 IF EXISTS("i:" + key) != 1 THEN GOTO 200
	50 LET value = LOAD("i:" + key)
	60 LET i = 0

	100 LET c = SUBSTR(value, i, 1)
	110 IF (c == ":") THEN GOTO 200
	120 LET tally_str = tally_str + c
	130 LET i = i + 1
	140 GOTO 100

	200 LET tally = ATOI(tally_str)
	210 IF ((tally & 1) == 1) THEN GOTO 1000
	220 IF SUBSTR(value, i+1, STRLEN(proposal)) == proposal THEN GOTO 300
	230 LET tally = 0

	300 LET tally = tally | SHL(1, LOAD(trustee) + 1)
	310 IF countVotes(tally) < LOAD("quorum") THEN GOTO 400
	320 LET tally = tally | 1

	400 STORE("i:" + key, ITOA(tally) + ":" + proposal)
	410 RETURN (tally & 1)

	1000 RETURN 0
End Function