diff --git a/contracts/Base64.sol b/contracts/Base64.sol deleted file mode 100644 index 4e08cd5..0000000 --- a/contracts/Base64.sol +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Provides a set of functions to operate with Base64 strings. - * - * _Available since v4.5._ - */ -library Base64 { - /** - * @dev Base64 Encoding/Decoding Table - */ - string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - /** - * @dev Converts a `bytes` to its Bytes64 `string` representation. - */ - function encode(bytes memory data) internal pure returns (string memory) { - /** - * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence - * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol - */ - if (data.length == 0) return ""; - - // Loads the table into memory - string memory table = _TABLE; - - // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter - // and split into 4 numbers of 6 bits. - // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up - // - `data.length + 2` -> Round up - // - `/ 3` -> Number of 3-bytes chunks - // - `4 *` -> 4 characters for each chunk - string memory result = new string(4 * ((data.length + 2) / 3)); - - /// @solidity memory-safe-assembly - assembly { - // Prepare the lookup table (skip the first "length" byte) - let tablePtr := add(table, 1) - - // Prepare result pointer, jump over length - let resultPtr := add(result, 32) - - // Run over the input, 3 bytes at a time - for { - let dataPtr := data - let endPtr := add(data, mload(data)) - } lt(dataPtr, endPtr) { - - } { - // Advance 3 bytes - dataPtr := add(dataPtr, 3) - let input := mload(dataPtr) - - // To write each character, shift the 3 bytes (18 bits) chunk - // 4 times in blocks of 6 bits for each character (18, 12, 6, 0) - // and apply logical AND with 0x3F which is the number of - // the previous character in the ASCII table prior to the Base64 Table - // The result is then added to the table to get the character to write, - // and finally write it in the result pointer but with a left shift - // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits - - mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) - resultPtr := add(resultPtr, 1) // Advance - - mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) - resultPtr := add(resultPtr, 1) // Advance - - mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F)))) - resultPtr := add(resultPtr, 1) // Advance - - mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F)))) - resultPtr := add(resultPtr, 1) // Advance - } - - // When data `bytes` is not exactly 3 bytes long - // it is padded with `=` characters at the end - switch mod(mload(data), 3) - case 1 { - mstore8(sub(resultPtr, 1), 0x3d) - mstore8(sub(resultPtr, 2), 0x3d) - } - case 2 { - mstore8(sub(resultPtr, 1), 0x3d) - } - } - - return result; - } -} diff --git a/contracts/CurioERC1155Wrapper.sol b/contracts/CurioERC1155Wrapper.sol index e58b30b..8aa5e55 100644 --- a/contracts/CurioERC1155Wrapper.sol +++ b/contracts/CurioERC1155Wrapper.sol @@ -2,10 +2,12 @@ pragma solidity ^0.8.17; import "./ERC1155.sol"; -import "./ICurio.sol"; +import "./IMastersFedi.sol"; import "./SafeMath.sol"; import "./Address.sol"; import "./IERC1155Metadata.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; +import "@openzeppelin/contracts/utils/Base64.sol"; contract CurioERC1155Wrapper is ERC1155, ERC1155Metadata_URI { using SafeMath for uint256; @@ -90,7 +92,7 @@ contract CurioERC1155Wrapper is ERC1155, ERC1155Metadata_URI { function wrap(uint256 _id, uint256 _quantity) external { address tokenContract = contracts[_id]; require(tokenContract != address(0), "invalid id"); - ICurio curio = ICurio(tokenContract); + IMastersFedi curio = IMastersFedi(tokenContract); // these are here for convenience because curio contract doesn't throw meaningful exceptions require(curio.balanceOf(msg.sender) >= _quantity, "insufficient curio balance"); @@ -124,7 +126,7 @@ contract CurioERC1155Wrapper is ERC1155, ERC1155Metadata_URI { address tokenContract = contracts[_id]; require(tokenContract != address(0), "invalid id"); - ICurio curio = ICurio(tokenContract); + IMastersFedi curio = IMastersFedi(tokenContract); require(curio.balanceOf(msg.sender) >= _quantity, "insufficient curio balance"); require(curio.allowance(msg.sender, address(this)) >= _quantity, "insufficient curio allowance"); @@ -149,7 +151,7 @@ contract CurioERC1155Wrapper is ERC1155, ERC1155Metadata_URI { function unwrap(uint256 _id, uint256 _quantity) external { address tokenContract = contracts[_id]; require(tokenContract != address(0), "invalid id"); - ICurio curio = ICurio(tokenContract); + IMastersFedi curio = IMastersFedi(tokenContract); require(balances[_id][msg.sender] >= _quantity, "insufficient balance"); balances[_id][msg.sender] = balances[_id][msg.sender].sub(_quantity); @@ -172,7 +174,7 @@ contract CurioERC1155Wrapper is ERC1155, ERC1155Metadata_URI { address tokenContract = contracts[_id]; require(tokenContract != address(0), "invalid id"); - ICurio curio = ICurio(tokenContract); + IMastersFedi curio = IMastersFedi(tokenContract); require(balances[_id][msg.sender] >= _quantity, "insufficient balance"); balances[_id][msg.sender] = balances[_id][msg.sender].sub(_quantity); diff --git a/contracts/IMastersFedi.sol b/contracts/IMastersFedi.sol new file mode 100644 index 0000000..0f61177 --- /dev/null +++ b/contracts/IMastersFedi.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.17; + +// Masters of the Fediverse is not quite ERC-20 compliant +interface IMastersFedi { + function balanceOf(address account) external view returns (uint256); + function allowance(address owner, address spender) external view returns (uint256); + function transferFrom(address _from, address _to, uint256 _value) external; + function transfer(address _to, uint256 _value) external; + function ipfs_hash() external view returns (string memory); + function name() external view returns (string memory); + function symbol() external view returns (string memory); + function description() external view returns (string memory); +} diff --git a/package-lock.json b/package-lock.json index 7f341dc..402d5ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "curio-wrapper", "version": "1.0.0", "license": "ISC", + "dependencies": { + "@openzeppelin/contracts": "^4.8.1" + }, "devDependencies": { "@truffle/hdwallet-provider": "^1.7.0", "ganache": "^7.7.3", @@ -1278,6 +1281,11 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@openzeppelin/contracts": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.8.1.tgz", + "integrity": "sha512-xQ6eUZl+RDyb/FiZe1h+U7qr/f4p/SrTSQcTPH2bjur3C5DbuW/zFgCU/b1P/xcIaEqJep+9ju4xDRi3rmChdQ==" + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -12336,6 +12344,11 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@openzeppelin/contracts": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.8.1.tgz", + "integrity": "sha512-xQ6eUZl+RDyb/FiZe1h+U7qr/f4p/SrTSQcTPH2bjur3C5DbuW/zFgCU/b1P/xcIaEqJep+9ju4xDRi3rmChdQ==" + }, "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", diff --git a/package.json b/package.json index d73d4ac..1e0cf27 100644 --- a/package.json +++ b/package.json @@ -19,5 +19,8 @@ "@truffle/hdwallet-provider": "^1.7.0", "ganache": "^7.7.3", "truffle": "^5.7.4" + }, + "dependencies": { + "@openzeppelin/contracts": "^4.8.1" } }