Last active
January 12, 2022 07:42
-
-
Save mwmwmw/682c4181919671031e53cef7268a866e to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.7+commit.e28d00a7.js&optimize=false&runs=200&gist=
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.0; | |
/// @title Base64 | |
/// @author Brecht Devos - <[email protected]> | |
/// @notice Provides functions for encoding/decoding base64 | |
library Base64 { | |
string internal constant TABLE_ENCODE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; | |
bytes internal constant TABLE_DECODE = hex"0000000000000000000000000000000000000000000000000000000000000000" | |
hex"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000" | |
hex"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000" | |
hex"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000"; | |
function encode(bytes memory data) internal pure returns (string memory) { | |
if (data.length == 0) return ''; | |
// load the table into memory | |
string memory table = TABLE_ENCODE; | |
// multiply by 4/3 rounded up | |
uint256 encodedLen = 4 * ((data.length + 2) / 3); | |
// add some extra buffer at the end required for the writing | |
string memory result = new string(encodedLen + 32); | |
assembly { | |
// set the actual output length | |
mstore(result, encodedLen) | |
// prepare the lookup table | |
let tablePtr := add(table, 1) | |
// input ptr | |
let dataPtr := data | |
let endPtr := add(dataPtr, mload(data)) | |
// result ptr, jump over length | |
let resultPtr := add(result, 32) | |
// run over the input, 3 bytes at a time | |
for {} lt(dataPtr, endPtr) {} | |
{ | |
// read 3 bytes | |
dataPtr := add(dataPtr, 3) | |
let input := mload(dataPtr) | |
// write 4 characters | |
mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) | |
resultPtr := add(resultPtr, 1) | |
mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) | |
resultPtr := add(resultPtr, 1) | |
mstore8(resultPtr, mload(add(tablePtr, and(shr( 6, input), 0x3F)))) | |
resultPtr := add(resultPtr, 1) | |
mstore8(resultPtr, mload(add(tablePtr, and( input, 0x3F)))) | |
resultPtr := add(resultPtr, 1) | |
} | |
// padding with '=' | |
switch mod(mload(data), 3) | |
case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) } | |
case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) } | |
} | |
return result; | |
} | |
function decode(string memory _data) internal pure returns (bytes memory) { | |
bytes memory data = bytes(_data); | |
if (data.length == 0) return new bytes(0); | |
require(data.length % 4 == 0, "invalid base64 decoder input"); | |
// load the table into memory | |
bytes memory table = TABLE_DECODE; | |
// every 4 characters represent 3 bytes | |
uint256 decodedLen = (data.length / 4) * 3; | |
// add some extra buffer at the end required for the writing | |
bytes memory result = new bytes(decodedLen + 32); | |
assembly { | |
// padding with '=' | |
let lastBytes := mload(add(data, mload(data))) | |
if eq(and(lastBytes, 0xFF), 0x3d) { | |
decodedLen := sub(decodedLen, 1) | |
if eq(and(lastBytes, 0xFFFF), 0x3d3d) { | |
decodedLen := sub(decodedLen, 1) | |
} | |
} | |
// set the actual output length | |
mstore(result, decodedLen) | |
// prepare the lookup table | |
let tablePtr := add(table, 1) | |
// input ptr | |
let dataPtr := data | |
let endPtr := add(dataPtr, mload(data)) | |
// result ptr, jump over length | |
let resultPtr := add(result, 32) | |
// run over the input, 4 characters at a time | |
for {} lt(dataPtr, endPtr) {} | |
{ | |
// read 4 characters | |
dataPtr := add(dataPtr, 4) | |
let input := mload(dataPtr) | |
// write 3 bytes | |
let output := add( | |
add( | |
shl(18, and(mload(add(tablePtr, and(shr(24, input), 0xFF))), 0xFF)), | |
shl(12, and(mload(add(tablePtr, and(shr(16, input), 0xFF))), 0xFF))), | |
add( | |
shl( 6, and(mload(add(tablePtr, and(shr( 8, input), 0xFF))), 0xFF)), | |
and(mload(add(tablePtr, and( input , 0xFF))), 0xFF) | |
) | |
) | |
mstore(resultPtr, shl(232, output)) | |
resultPtr := add(resultPtr, 3) | |
} | |
} | |
return result; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-3.0 | |
pragma solidity ^0.8.0; | |
import "./Base64.sol"; | |
struct Game { | |
address p1; | |
address p2; | |
string result; | |
} | |
// GAS COST 1 = 176749 | |
// GAS COST 2 = 96377 | |
// GAS COST 3 = 133765 ???? | |
contract RPS { | |
uint256 public gameCount; | |
mapping(uint256 => Game) public games; | |
function toString(address account) public pure returns(string memory) { | |
return toString(abi.encodePacked(account)); | |
} | |
function toString(bytes memory data) public pure returns(string memory) { | |
bytes memory alphabet = "0123456789abcdef"; | |
bytes memory str = new bytes(2 + data.length * 2); | |
str[0] = "0"; | |
str[1] = "x"; | |
for (uint i = 0; i < data.length; i++) { | |
str[2+i*2] = alphabet[uint(uint8(data[i] >> 4))]; | |
str[3+i*2] = alphabet[uint(uint8(data[i] & 0x0f))]; | |
} | |
return string(str); | |
} | |
function Play(address player1, address player2) public returns(string memory) { | |
Game memory game; | |
game.p1 = player1; | |
game.p2 = player2; | |
uint256 p1fate = uint256( | |
keccak256( | |
abi.encodePacked( | |
gameCount, | |
player1, | |
block.difficulty, | |
block.timestamp | |
) | |
) | |
)%3; | |
uint256 p2fate = uint256( | |
keccak256( | |
abi.encodePacked( | |
gameCount, | |
player2, | |
block.difficulty, | |
block.timestamp | |
) | |
) | |
)%3; | |
if(p1fate == 0 && p2fate == 2 || p1fate == 1 && p2fate == 0 || p1fate == 2 && p2fate == 1) { | |
game.result = "Player 1 Wins"; | |
} | |
if(p2fate == 0 && p1fate == 2 || p2fate == 1 && p1fate == 0 || p2fate == 2 && p1fate == 1) { | |
game.result = "Player 2 Wins"; | |
} | |
if(p2fate == 0 && p1fate == 0 || p2fate == 1 && p1fate == 1 || p2fate == 2 && p1fate == 2) { | |
game.result = "Draw"; | |
} | |
games[gameCount++] = game; | |
return string(abi.encodePacked( | |
'{"player1":"', | |
toString(game.p1), | |
'","player2":"', | |
toString(game.p2), | |
'","result":"', | |
game.result, | |
'"}' | |
)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-3.0 | |
pragma solidity ^0.8.0; | |
import "./Base64.sol"; | |
struct Game { | |
address p1; | |
address p2; | |
uint256 p1fate; | |
uint256 p2fate; | |
} | |
contract RPS { | |
uint256 public gameCount; | |
mapping(uint256 => Game) public games; | |
function toString(address account) public pure returns(string memory) { | |
return toString(abi.encodePacked(account)); | |
} | |
function toString(bytes memory data) public pure returns(string memory) { | |
bytes memory alphabet = "0123456789abcdef"; | |
bytes memory str = new bytes(2 + data.length * 2); | |
str[0] = "0"; | |
str[1] = "x"; | |
for (uint i = 0; i < data.length; i++) { | |
str[2+i*2] = alphabet[uint(uint8(data[i] >> 4))]; | |
str[3+i*2] = alphabet[uint(uint8(data[i] & 0x0f))]; | |
} | |
return string(str); | |
} | |
function Play(address player1, address player2) public { | |
Game memory game; | |
game.p1 = player1; | |
game.p2 = player2; | |
game.p1fate = uint256( | |
keccak256( | |
abi.encodePacked( | |
gameCount, | |
player1, | |
block.difficulty, | |
block.timestamp | |
) | |
) | |
)%3; | |
game.p2fate = uint256( | |
keccak256( | |
abi.encodePacked( | |
gameCount, | |
player2, | |
block.difficulty, | |
block.timestamp | |
) | |
) | |
)%3; | |
games[gameCount++] = game; | |
} | |
function getGame(uint256 gameId) public view returns (string memory) { | |
Game memory game = games[gameId]; | |
string memory result; | |
if(game.p1fate == 0 && game.p2fate == 2 || game.p1fate == 1 && game.p2fate == 0 || game.p1fate == 2 && game.p2fate == 1) { | |
result = "Player 1 Wins"; | |
} | |
if(game.p2fate == 0 && game.p1fate == 2 || game.p2fate == 1 && game.p1fate == 0 || game.p2fate == 2 && game.p1fate == 1) { | |
result = "Player 2 Wins"; | |
} | |
if(game.p2fate == 0 && game.p1fate == 0 || game.p2fate == 1 && game.p1fate == 1 || game.p2fate == 2 && game.p1fate == 2) { | |
result = "Draw"; | |
} | |
return string(abi.encodePacked( | |
'{"player1":"', | |
toString(game.p1), | |
'","player2":"', | |
toString(game.p2), | |
'","result":"', | |
result, | |
'"}' | |
)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-3.0 | |
pragma solidity ^0.8.0; | |
import "./Base64.sol"; | |
struct Game { | |
address p1; | |
address p2; | |
uint256 seed1; | |
uint256 seed2; | |
} | |
contract RPS { | |
uint256 public gameCount; | |
mapping(uint256 => Game) public games; | |
function toString(address account) public pure returns(string memory) { | |
return toString(abi.encodePacked(account)); | |
} | |
function toString(bytes memory data) public pure returns(string memory) { | |
bytes memory alphabet = "0123456789abcdef"; | |
bytes memory str = new bytes(2 + data.length * 2); | |
str[0] = "0"; | |
str[1] = "x"; | |
for (uint i = 0; i < data.length; i++) { | |
str[2+i*2] = alphabet[uint(uint8(data[i] >> 4))]; | |
str[3+i*2] = alphabet[uint(uint8(data[i] & 0x0f))]; | |
} | |
return string(str); | |
} | |
function Play(address player1, address player2) public { | |
Game memory game; | |
game.p1 = player1; | |
game.p2 = player2; | |
game.seed1 = block.difficulty; | |
game.seed2 = block.timestamp; | |
games[gameCount++] = game; | |
} | |
function getGame(uint256 gameId) public view returns (string memory) { | |
Game memory game = games[gameId]; | |
uint256 p1fate = uint256( | |
keccak256( | |
abi.encodePacked( | |
gameId, | |
game.p1, | |
game.seed1, | |
game.seed2 | |
) | |
) | |
)%3; | |
uint256 p2fate = uint256( | |
keccak256( | |
abi.encodePacked( | |
gameId, | |
game.p2, | |
game.seed1, | |
game.seed2 | |
) | |
) | |
)%3; | |
string memory result; | |
if(p1fate == 0 && p2fate == 2 || p1fate == 1 && p2fate == 0 || p1fate == 2 && p2fate == 1) { | |
result = "Player 1 Wins"; | |
} | |
if(p2fate == 0 && p1fate == 2 || p2fate == 1 && p1fate == 0 || p2fate == 2 && p1fate == 1) { | |
result = "Player 2 Wins"; | |
} | |
if(p2fate == 0 && p1fate == 0 || p2fate == 1 && p1fate == 1 || p2fate == 2 && p1fate == 2) { | |
result = "Draw"; | |
} | |
return string(abi.encodePacked( | |
'{"player1":"', | |
toString(game.p1), | |
'","player2":"', | |
toString(game.p2), | |
'","result":"', | |
result, | |
'"}' | |
)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-3.0 | |
pragma solidity ^0.8.0; | |
import "./Base64.sol"; | |
contract Simple { | |
string myValue; | |
function setValue(string memory a, string memory b) public { | |
myValue = string(abi.encodePacked(a, " ", b)); | |
} | |
function getValue() public view returns (string memory) { | |
return myValue; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-3.0 | |
pragma solidity ^0.8.0; | |
import "./Base64.sol"; | |
contract Simple { | |
string myValue; | |
// 49370 gas | |
function setValue(string memory a, string memory b) public { | |
myValue = Base64.encode(abi.encodePacked(a, " ", b)); | |
} | |
function getValue() public view returns (string memory) { | |
return myValue; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-3.0 | |
pragma solidity ^0.8.0; | |
import "./Base64.sol"; | |
contract Simple { | |
bytes myValue; | |
// 47174 gas | |
function setValue(string memory a, string memory b) public { | |
myValue = abi.encodePacked(a, " ", b); | |
} | |
function getValue() public view returns (string memory) { | |
return Base64.encode(myValue); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: GPL-3.0 | |
pragma solidity ^0.8.0; | |
import "./Base64.sol"; | |
contract Simple { | |
string myValue1; | |
string myValue2; | |
// 68687 gas | |
function setValue(string memory a, string memory b) public { | |
myValue1 = a; | |
myValue2 = b; | |
} | |
function getValue() public view returns (string memory) { | |
return Base64.encode(abi.encodePacked(myValue1, " ", myValue2)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment