@lukso/lsp20-contracts 0.15.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/contracts/ILSP20CallVerifier.sol +39 -0
- package/contracts/LSP20CallVerification.sol +120 -0
- package/contracts/LSP20Constants.sol +17 -0
- package/contracts/LSP20Errors.sol +21 -0
- package/dist/index.cjs +18 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.mts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.mjs +14 -0
- package/package.json +44 -0
package/README.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# LSP20 Call Verification · [](https://www.npmjs.com/package/@lukso/lsp20-contracts)
|
2
|
+
|
3
|
+
Package for the LSP20 Call Verification standard.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```bash
|
8
|
+
npm i @lukso/lsp20-contracts
|
9
|
+
```
|
@@ -0,0 +1,39 @@
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
2
|
+
pragma solidity ^0.8.4;
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @title Interface for the LSP20 Call Verification standard, a set of functions intended to perform verifications on behalf of another contract.
|
6
|
+
*
|
7
|
+
* @dev Interface to be inherited for contract supporting LSP20-CallVerification
|
8
|
+
*/
|
9
|
+
interface ILSP20CallVerifier {
|
10
|
+
/**
|
11
|
+
* @return returnedStatus MUST return the first 3 bytes of `lsp20VerifyCall(address,uint256,bytes)` function selector if the call to
|
12
|
+
* the function is allowed, concatened with a byte that determines if the lsp20VerifyCallResult function should
|
13
|
+
* be called after the original function call. The byte that invoke the lsp20VerifyCallResult function is strictly `0x01`.
|
14
|
+
*
|
15
|
+
* @param requestor The address that requested to make the call to `target`.
|
16
|
+
* @param target The address of the contract that implements the `LSP20CallVerification` interface.
|
17
|
+
* @param caller The address who called the function on the `target` contract.
|
18
|
+
* @param value The value sent by the caller to the function called on the msg.sender
|
19
|
+
* @param callData The calldata sent by the caller to the msg.sender
|
20
|
+
*/
|
21
|
+
function lsp20VerifyCall(
|
22
|
+
address requestor,
|
23
|
+
address target,
|
24
|
+
address caller,
|
25
|
+
uint256 value,
|
26
|
+
bytes memory callData
|
27
|
+
) external returns (bytes4 returnedStatus);
|
28
|
+
|
29
|
+
/**
|
30
|
+
* @return MUST return the lsp20VerifyCallResult function selector if the call to the function is allowed
|
31
|
+
*
|
32
|
+
* @param callHash The keccak256 hash of the parameters of {lsp20VerifyCall} concatenated
|
33
|
+
* @param callResult The value result of the function called on the msg.sender
|
34
|
+
*/
|
35
|
+
function lsp20VerifyCallResult(
|
36
|
+
bytes32 callHash,
|
37
|
+
bytes memory callResult
|
38
|
+
) external returns (bytes4);
|
39
|
+
}
|
@@ -0,0 +1,120 @@
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
2
|
+
pragma solidity ^0.8.4;
|
3
|
+
|
4
|
+
// interfaces
|
5
|
+
import {ILSP20CallVerifier as ILSP20} from "./ILSP20CallVerifier.sol";
|
6
|
+
|
7
|
+
// errors
|
8
|
+
import {
|
9
|
+
LSP20CallVerificationFailed,
|
10
|
+
LSP20CallingVerifierFailed,
|
11
|
+
LSP20EOACannotVerifyCall
|
12
|
+
} from "./LSP20Errors.sol";
|
13
|
+
|
14
|
+
/**
|
15
|
+
* @title Implementation of a contract calling the verification functions according to LSP20 - Call Verification standard.
|
16
|
+
*
|
17
|
+
* @dev Module to be inherited used to verify the execution of functions according to a verifier address.
|
18
|
+
* Verification can happen before or after execution based on a returnedStatus.
|
19
|
+
*/
|
20
|
+
abstract contract LSP20CallVerification {
|
21
|
+
/**
|
22
|
+
* @dev Calls {lsp20VerifyCall} function on the logicVerifier.
|
23
|
+
*
|
24
|
+
* @custom:info
|
25
|
+
* - Reverts in case the value returned does not match the returned status (lsp20VerifyCall selector).
|
26
|
+
* - Returns whether a verification after the execution should happen based on the last byte of the `returnedStatus`.
|
27
|
+
* - Reverts with no reason if the data returned by `ILSP20(logicVerifier).lsp20VerifyCall(...)` cannot be decoded (_e.g:_ any other data type besides `bytes4`).
|
28
|
+
* See this link for more info: https://forum.soliditylang.org/t/call-for-feedback-the-future-of-try-catch-in-solidity/1497.
|
29
|
+
*/
|
30
|
+
function _verifyCall(
|
31
|
+
address logicVerifier
|
32
|
+
) internal virtual returns (bool verifyAfter) {
|
33
|
+
if (logicVerifier.code.length == 0) {
|
34
|
+
revert LSP20EOACannotVerifyCall(logicVerifier);
|
35
|
+
}
|
36
|
+
|
37
|
+
// Reverts with no reason if the returned data type is not a `bytes4` value
|
38
|
+
try
|
39
|
+
ILSP20(logicVerifier).lsp20VerifyCall(
|
40
|
+
msg.sender,
|
41
|
+
address(this),
|
42
|
+
msg.sender,
|
43
|
+
msg.value,
|
44
|
+
msg.data
|
45
|
+
)
|
46
|
+
returns (bytes4 returnedStatus) {
|
47
|
+
if (
|
48
|
+
bytes3(returnedStatus) !=
|
49
|
+
bytes3(ILSP20.lsp20VerifyCall.selector)
|
50
|
+
) {
|
51
|
+
revert LSP20CallVerificationFailed({
|
52
|
+
postCall: false,
|
53
|
+
returnedStatus: returnedStatus
|
54
|
+
});
|
55
|
+
}
|
56
|
+
|
57
|
+
return returnedStatus[3] == 0x01;
|
58
|
+
} catch (bytes memory errorData) {
|
59
|
+
_revertWithLSP20DefaultError(false, errorData);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
/**
|
64
|
+
* @dev Calls {lsp20VerifyCallResult} function on the logicVerifier.
|
65
|
+
*
|
66
|
+
* @custom:info
|
67
|
+
* - Reverts in case the value returned does not match the returned status (lsp20VerifyCallResult selector).
|
68
|
+
* - Reverts with no reason if the data returned by `ILSP20(logicVerifier).lsp20VerifyCallResult(...)` cannot be decoded (_e.g:_ any other data type besides `bytes4`).
|
69
|
+
* See this link for more info: https://forum.soliditylang.org/t/call-for-feedback-the-future-of-try-catch-in-solidity/1497.
|
70
|
+
*/
|
71
|
+
function _verifyCallResult(
|
72
|
+
address logicVerifier,
|
73
|
+
bytes memory callResult
|
74
|
+
) internal virtual {
|
75
|
+
// Reverts with no reason if the returned data type is not a `bytes4` value
|
76
|
+
try
|
77
|
+
ILSP20(logicVerifier).lsp20VerifyCallResult(
|
78
|
+
keccak256(
|
79
|
+
abi.encodePacked(
|
80
|
+
msg.sender,
|
81
|
+
address(this),
|
82
|
+
msg.sender,
|
83
|
+
msg.value,
|
84
|
+
msg.data
|
85
|
+
)
|
86
|
+
),
|
87
|
+
callResult
|
88
|
+
)
|
89
|
+
returns (bytes4 returnedStatus) {
|
90
|
+
if (returnedStatus != ILSP20.lsp20VerifyCallResult.selector) {
|
91
|
+
revert LSP20CallVerificationFailed({
|
92
|
+
postCall: true,
|
93
|
+
returnedStatus: returnedStatus
|
94
|
+
});
|
95
|
+
}
|
96
|
+
|
97
|
+
return;
|
98
|
+
} catch (bytes memory errorData) {
|
99
|
+
_revertWithLSP20DefaultError(true, errorData);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
function _revertWithLSP20DefaultError(
|
104
|
+
bool postCall,
|
105
|
+
bytes memory returnedData
|
106
|
+
) internal pure virtual {
|
107
|
+
// Look for revert reason and bubble it up if present
|
108
|
+
if (returnedData.length != 0) {
|
109
|
+
// The easiest way to bubble the revert reason is using memory via assembly
|
110
|
+
// solhint-disable no-inline-assembly
|
111
|
+
/// @solidity memory-safe-assembly
|
112
|
+
assembly {
|
113
|
+
let returndata_size := mload(returnedData)
|
114
|
+
revert(add(32, returnedData), returndata_size)
|
115
|
+
}
|
116
|
+
} else {
|
117
|
+
revert LSP20CallingVerifierFailed(postCall);
|
118
|
+
}
|
119
|
+
}
|
120
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
2
|
+
pragma solidity ^0.8.4;
|
3
|
+
|
4
|
+
// bytes4(keccak256("LSP20CallVerification"))
|
5
|
+
bytes4 constant _INTERFACEID_LSP20_CALL_VERIFICATION = 0x1a0eb6a5;
|
6
|
+
|
7
|
+
// `lsp20VerifyCall(address,address,address,uint256,bytes)` selector XOR `lsp20VerifyCallResult(bytes32,bytes)` selector
|
8
|
+
bytes4 constant _INTERFACEID_LSP20_CALL_VERIFIER = 0x0d6ecac7;
|
9
|
+
|
10
|
+
// bytes4(bytes.concat(bytes3(ILSP20.lsp20VerifyCall.selector), hex"01"))
|
11
|
+
bytes4 constant _LSP20_VERIFY_CALL_SUCCESS_VALUE_WITH_POST_VERIFICATION = 0xde928f01;
|
12
|
+
|
13
|
+
// bytes4(bytes.concat(bytes3(ILSP20.lsp20VerifyCall.selector), hex"00"))
|
14
|
+
bytes4 constant _LSP20_VERIFY_CALL_SUCCESS_VALUE_WITHOUT_POST_VERIFICATION = 0xde928f00;
|
15
|
+
|
16
|
+
// bytes4(ILSP20.lsp20VerifyCallResult.selector)
|
17
|
+
bytes4 constant _LSP20_VERIFY_CALL_RESULT_SUCCESS_VALUE = 0xd3fc45d3;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
2
|
+
pragma solidity ^0.8.4;
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @dev reverts when the call to the owner fail with no revert reason
|
6
|
+
* @param postCall True if the execution call was done, False otherwise
|
7
|
+
*/
|
8
|
+
error LSP20CallingVerifierFailed(bool postCall);
|
9
|
+
|
10
|
+
/**
|
11
|
+
* @dev reverts when the call to the owner does not return the LSP20 success value
|
12
|
+
* @param postCall True if the execution call was done, False otherwise
|
13
|
+
* @param returnedStatus The bytes4 decoded data returned by the logic verifier.
|
14
|
+
*/
|
15
|
+
error LSP20CallVerificationFailed(bool postCall, bytes4 returnedStatus);
|
16
|
+
|
17
|
+
/**
|
18
|
+
* @dev Reverts when the logic verifier is an Externally Owned Account (EOA) that cannot return the LSP20 success value.
|
19
|
+
* @param logicVerifier The address of the logic verifier
|
20
|
+
*/
|
21
|
+
error LSP20EOACannotVerifyCall(address logicVerifier);
|
package/dist/index.cjs
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const INTERFACE_ID_LSP20CallVerification = "0x1a0eb6a5";
|
4
|
+
const INTERFACE_ID_LSP20CallVerifier = "0x0d6ecac7";
|
5
|
+
const LSP20_SUCCESS_VALUES = {
|
6
|
+
VERIFY_CALL: {
|
7
|
+
// bytes3(keccak256("lsp20VerifyCall(address,address,address,uint256,bytes)")) + "0x00"
|
8
|
+
NO_POST_VERIFICATION: "0xde928f00",
|
9
|
+
// bytes3(keccak256("lsp20VerifyCall(address,address,address,uint256,bytes)")) + "0x01"
|
10
|
+
WITH_POST_VERIFICATION: "0xde928f01"
|
11
|
+
},
|
12
|
+
// bytes4(keccak256("lsp20VerifyCallResult(bytes32,bytes)"))
|
13
|
+
VERIFY_CALL_RESULT: "0xd3fc45d3"
|
14
|
+
};
|
15
|
+
|
16
|
+
exports.INTERFACE_ID_LSP20CallVerification = INTERFACE_ID_LSP20CallVerification;
|
17
|
+
exports.INTERFACE_ID_LSP20CallVerifier = INTERFACE_ID_LSP20CallVerifier;
|
18
|
+
exports.LSP20_SUCCESS_VALUES = LSP20_SUCCESS_VALUES;
|
package/dist/index.d.cts
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
declare const INTERFACE_ID_LSP20CallVerification = "0x1a0eb6a5";
|
2
|
+
declare const INTERFACE_ID_LSP20CallVerifier = "0x0d6ecac7";
|
3
|
+
/**
|
4
|
+
* @dev values returned by the `lsp20VerifyCall` and `lsp20VerifyCallResult` functions of the LSP20 standard.
|
5
|
+
* Can be used to check if a calldata payload was check and verified.
|
6
|
+
*/
|
7
|
+
declare const LSP20_SUCCESS_VALUES: {
|
8
|
+
VERIFY_CALL: {
|
9
|
+
NO_POST_VERIFICATION: string;
|
10
|
+
WITH_POST_VERIFICATION: string;
|
11
|
+
};
|
12
|
+
VERIFY_CALL_RESULT: string;
|
13
|
+
};
|
14
|
+
|
15
|
+
export { INTERFACE_ID_LSP20CallVerification, INTERFACE_ID_LSP20CallVerifier, LSP20_SUCCESS_VALUES };
|
package/dist/index.d.mts
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
declare const INTERFACE_ID_LSP20CallVerification = "0x1a0eb6a5";
|
2
|
+
declare const INTERFACE_ID_LSP20CallVerifier = "0x0d6ecac7";
|
3
|
+
/**
|
4
|
+
* @dev values returned by the `lsp20VerifyCall` and `lsp20VerifyCallResult` functions of the LSP20 standard.
|
5
|
+
* Can be used to check if a calldata payload was check and verified.
|
6
|
+
*/
|
7
|
+
declare const LSP20_SUCCESS_VALUES: {
|
8
|
+
VERIFY_CALL: {
|
9
|
+
NO_POST_VERIFICATION: string;
|
10
|
+
WITH_POST_VERIFICATION: string;
|
11
|
+
};
|
12
|
+
VERIFY_CALL_RESULT: string;
|
13
|
+
};
|
14
|
+
|
15
|
+
export { INTERFACE_ID_LSP20CallVerification, INTERFACE_ID_LSP20CallVerifier, LSP20_SUCCESS_VALUES };
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
declare const INTERFACE_ID_LSP20CallVerification = "0x1a0eb6a5";
|
2
|
+
declare const INTERFACE_ID_LSP20CallVerifier = "0x0d6ecac7";
|
3
|
+
/**
|
4
|
+
* @dev values returned by the `lsp20VerifyCall` and `lsp20VerifyCallResult` functions of the LSP20 standard.
|
5
|
+
* Can be used to check if a calldata payload was check and verified.
|
6
|
+
*/
|
7
|
+
declare const LSP20_SUCCESS_VALUES: {
|
8
|
+
VERIFY_CALL: {
|
9
|
+
NO_POST_VERIFICATION: string;
|
10
|
+
WITH_POST_VERIFICATION: string;
|
11
|
+
};
|
12
|
+
VERIFY_CALL_RESULT: string;
|
13
|
+
};
|
14
|
+
|
15
|
+
export { INTERFACE_ID_LSP20CallVerification, INTERFACE_ID_LSP20CallVerifier, LSP20_SUCCESS_VALUES };
|
package/dist/index.mjs
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
const INTERFACE_ID_LSP20CallVerification = "0x1a0eb6a5";
|
2
|
+
const INTERFACE_ID_LSP20CallVerifier = "0x0d6ecac7";
|
3
|
+
const LSP20_SUCCESS_VALUES = {
|
4
|
+
VERIFY_CALL: {
|
5
|
+
// bytes3(keccak256("lsp20VerifyCall(address,address,address,uint256,bytes)")) + "0x00"
|
6
|
+
NO_POST_VERIFICATION: "0xde928f00",
|
7
|
+
// bytes3(keccak256("lsp20VerifyCall(address,address,address,uint256,bytes)")) + "0x01"
|
8
|
+
WITH_POST_VERIFICATION: "0xde928f01"
|
9
|
+
},
|
10
|
+
// bytes4(keccak256("lsp20VerifyCallResult(bytes32,bytes)"))
|
11
|
+
VERIFY_CALL_RESULT: "0xd3fc45d3"
|
12
|
+
};
|
13
|
+
|
14
|
+
export { INTERFACE_ID_LSP20CallVerification, INTERFACE_ID_LSP20CallVerifier, LSP20_SUCCESS_VALUES };
|
package/package.json
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
{
|
2
|
+
"name": "@lukso/lsp20-contracts",
|
3
|
+
"version": "0.15.0-rc.0",
|
4
|
+
"description": "Package for the LSP20 Call Verification standard",
|
5
|
+
"license": "Apache-2.0",
|
6
|
+
"author": "",
|
7
|
+
"main": "./dist/index.cjs",
|
8
|
+
"module": "./dist/index.mjs",
|
9
|
+
"typings": "./dist/index.d.ts",
|
10
|
+
"exports": {
|
11
|
+
".": {
|
12
|
+
"require": "./dist/index.cjs",
|
13
|
+
"import": "./dist/index.mjs",
|
14
|
+
"types": "./dist/index.d.ts"
|
15
|
+
},
|
16
|
+
"./artifacts/*": "./artifacts/*",
|
17
|
+
"./package.json": "./package.json"
|
18
|
+
},
|
19
|
+
"files": [
|
20
|
+
"contracts/**/*.sol",
|
21
|
+
"!contracts/Mocks/**/*.sol",
|
22
|
+
"artifacts/*.json",
|
23
|
+
"dist",
|
24
|
+
"./README.md"
|
25
|
+
],
|
26
|
+
"keywords": [
|
27
|
+
"LUKSO",
|
28
|
+
"LSP",
|
29
|
+
"Blockchain",
|
30
|
+
"Standards",
|
31
|
+
"Smart Contracts",
|
32
|
+
"Ethereum",
|
33
|
+
"EVM",
|
34
|
+
"Solidity"
|
35
|
+
],
|
36
|
+
"scripts": {
|
37
|
+
"build": "hardhat compile --show-stack-traces",
|
38
|
+
"build:js": "unbuild",
|
39
|
+
"clean": "hardhat clean && rm -Rf dist/",
|
40
|
+
"format": "prettier --write .",
|
41
|
+
"lint": "eslint . --ext .ts,.js",
|
42
|
+
"lint:solidity": "solhint 'contracts/**/*.sol' && prettier --check 'contracts/**/*.sol'"
|
43
|
+
}
|
44
|
+
}
|