Skip to content

Commit

Permalink
Merge pull request #59 from Tenderize/nv/fix-decode-unlock-id
Browse files Browse the repository at this point in the history
Improve unlock ID decoding
  • Loading branch information
kyriediculous committed Jul 29, 2023
2 parents b849eb6 + ea295f1 commit ebb0f9a
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 18 deletions.
8 changes: 4 additions & 4 deletions src/unlocks/Renderer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Initializable } from "openzeppelin-contracts-upgradeable/proxy/utils/In
import { UUPSUpgradeable } from "openzeppelin-contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import { OwnableUpgradeable } from "openzeppelin-contracts-upgradeable/access/OwnableUpgradeable.sol";

import { Unlocks } from "core/unlocks/Unlocks.sol";
import { Unlocks, Metadata } from "core/unlocks/Unlocks.sol";
import { Base64 } from "core/unlocks/Base64.sol";

// solhint-disable quotes
Expand All @@ -43,7 +43,7 @@ contract Renderer is Initializable, UUPSUpgradeable, OwnableUpgradeable {
* @param id ID of the unlock
*/
function json(uint256 id) external view returns (string memory) {
Unlocks.Metadata memory data = Unlocks(msg.sender).getMetadata(id);
Metadata memory data = Unlocks(msg.sender).getMetadata(id);

return string(
abi.encodePacked(
Expand All @@ -64,7 +64,7 @@ contract Renderer is Initializable, UUPSUpgradeable, OwnableUpgradeable {
);
}

function _serializeMetadata(Unlocks.Metadata memory data) internal pure returns (string memory metadataString) {
function _serializeMetadata(Metadata memory data) internal pure returns (string memory metadataString) {
metadataString = string(
abi.encodePacked(
'{"trait_type": "maturity", "value":',
Expand All @@ -83,7 +83,7 @@ contract Renderer is Initializable, UUPSUpgradeable, OwnableUpgradeable {
);
}

function svg(Unlocks.Metadata memory data) internal pure returns (string memory) {
function svg(Metadata memory data) internal pure returns (string memory) {
return string(
abi.encodePacked(
'<svg width="290" height="500" viewBox="0 0 290 500" xmlns="http://www.w3.org/2000/svg"',
Expand Down
21 changes: 11 additions & 10 deletions src/unlocks/Unlocks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ pragma solidity 0.8.17;
/// @notice ERC721 contract for unlock tokens
/// @dev Creates an NFT for staked tokens pending unlock. Each Unlock has an amount and a maturity date.

contract Unlocks is ERC721 {
struct Metadata {
uint256 amount;
uint256 maturity;
uint256 tokenId;
string symbol;
string name;
address validator;
}
struct Metadata {
uint256 amount;
uint256 maturity;
uint256 tokenId;
string symbol;
string name;
address validator;
}

contract Unlocks is ERC721 {
Registry private immutable registry;
Renderer private immutable renderer;

Expand Down Expand Up @@ -115,6 +115,7 @@ contract Unlocks is ERC721 {
}

function _decodeTokenId(uint256 tokenId) internal pure virtual returns (address tenderizer, uint96 id) {
return (address(bytes20(bytes32(tokenId))), uint96(bytes12(bytes32(tokenId) << 160)));
bytes32 a = bytes32(tokenId);
return (address(bytes20(a)), uint96(bytes12(a << 160)));
}
}
6 changes: 3 additions & 3 deletions test/unlocks/Renderer.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Initializable } from "openzeppelin-contracts-upgradeable/proxy/utils/In
import { UUPSUpgradeable } from "openzeppelin-contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

import { Renderer } from "core/unlocks/Renderer.sol";
import { Unlocks } from "core/unlocks/Unlocks.sol";
import { Unlocks, Metadata } from "core/unlocks/Unlocks.sol";
import { Base64 } from "core/unlocks/Base64.sol";
import { UUPSTestHelper } from "test/helpers/UUPSTestHelper.sol";

Expand Down Expand Up @@ -58,8 +58,8 @@ contract RendererTest is Test {
address private tenderizer = vm.addr(3);
address private validator = vm.addr(4);
uint256 private id = 1;
Unlocks.Metadata private metadata =
Unlocks.Metadata({ amount: 100, maturity: 1000, tokenId: id, symbol: "GRT", name: "Graph", validator: validator });
Metadata private metadata =
Metadata({ amount: 100, maturity: 1000, tokenId: id, symbol: "GRT", name: "Graph", validator: validator });
RendererV1 private rendererV1;

bytes32 internal constant IMPL_SLOT = bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1);
Expand Down
27 changes: 26 additions & 1 deletion test/unlocks/Unlocks.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { Renderer } from "core/unlocks/Renderer.sol";
import { Registry } from "core/registry/Registry.sol";
import { Tenderizer } from "core/tenderizer/Tenderizer.sol";
import { TenderizerImmutableArgs } from "core/tenderizer/TenderizerBase.sol";
import { Unlocks } from "core/unlocks/Unlocks.sol";
import { Unlocks, Metadata } from "core/unlocks/Unlocks.sol";

// solhint-disable func-name-mixedcase
contract UnlockTest is Test {
Expand Down Expand Up @@ -135,6 +135,31 @@ contract UnlockTest is Test {
unlocks.tokenURI(1);
}

function test_getMetadata() public {
address tenderizer = address(this);
// create an unlock
uint256 lockId = 1337;
vm.mockCall(registry, abi.encodeCall(Registry.isTenderizer, (tenderizer)), abi.encode(true));
uint256 tokenId = unlocks.createUnlock(msg.sender, lockId);

vm.mockCall(tenderizer, abi.encodeCall(Tenderizer.previewWithdraw, (lockId)), abi.encode((1 ether)));
vm.mockCall(tenderizer, abi.encodeCall(Tenderizer.unlockMaturity, (lockId)), abi.encode((block.timestamp)));
vm.mockCall(tenderizer, abi.encodeCall(TenderizerImmutableArgs.validator, ()), abi.encode((validator)));
vm.mockCall(tenderizer, abi.encodeCall(TenderizerImmutableArgs.asset, ()), abi.encode((asset)));
vm.mockCall(asset, abi.encodeCall(IERC20Metadata.symbol, ()), abi.encode(("TEST")));
vm.mockCall(asset, abi.encodeCall(IERC20Metadata.name, ()), abi.encode(("Test Token")));
// get meta data

Metadata memory d = unlocks.getMetadata(tokenId);

assertEq(d.tokenId, lockId);
assertEq(d.amount, 1 ether);
assertEq(d.maturity, block.timestamp);
assertEq(d.symbol, "TEST");
assertEq(d.name, "Test Token");
assertEq(d.validator, validator);
}

// helpers
function _decodeTokenId(uint256 tokenId) internal pure virtual returns (address tenderizer, uint96 id) {
return (address(bytes20(bytes32(tokenId))), uint96(bytes12(bytes32(tokenId) << 160)));
Expand Down

0 comments on commit ebb0f9a

Please sign in to comment.