Note: This project is still under initial development, and not ready yet. It's currently a frankenstein between Foundry and Ape.
A Solidity smart contract for making sure the smart contract caller has accepted the latest terms of service.
- Record on-chain that users have accepted some sort of a disclaimer
- Enforce users to accept disclaimers when they use with the smart contract
- User signs an EIP-191 message from their wallet
- Multisignature wallet and protocol friendly EIP-1271 is supported
- Python 3.10+
- Foundry
Deploy TermsOfService smart contract for your chain
- Each deployment has its own smart contract address
- Each chain needs its own deployment
- Each TermsOfService tracks the currently active terms of service text
Creating terms of service
- Create a Markdown/plain text terms of service file
- Must be dated
- Must have a version number counter start from 1, then 2
- Record SHA-256 bit hash of the text
- Use update script to bump the new terms of service live
- The smart contract has
canProceed
function to check if a particular address has signed the latest terms of service version - The user signs a template message with their wallet. Note that this message only refers to the actual terms of service based on its version, hash, date and link,
- The address must have always signed the latest terms of service, and should be prompted to sign again if this is not the case
- The terms of service signing payload can be passed part as another smart contract transaction, and does not need to be a separate transaction
On hashes: There are two hashes. One for the actual terms of service file (never referred in the smart contracts) and one for the message (template-based) that users need to sign with their wallet.
- Arbitrum:
0xDCD7C644a6AA72eb2f86781175b18ADc30Aa4f4d
- Polygon:
0xbe1418df0bAd87577de1A41385F19c6e77312780
- Ethereum:
0xd63c1bE9D8B56CCcD6fd2Dd9F9c030c6a9916f5F
(latest hashb24acbfc1295902f1b26e0815e32e6edbdb67c0dacb9b378a556035f7f9b6c52
)
Install framework with Poetry:
poetry install
poetry shell
ape compile
poetry shell
# TODO: there is a bug in pytest/ape test that it does not find the tests
# unless you explicitly pass it the tests folder
ape test tests
Using Foundry.
Compile:
foundryup
forge build
Then:
export $TERMS_OF_SERVICE_DEPLOY_PRIVATE_KEY=
export JSON_RPC_ARBITRUM=
export ARBISCAN_API_KEY=
forge create \
--rpc-url $JSON_RPC_ARBITRUM \
--private-key $TERMS_OF_SERVICE_DEPLOY_PRIVATE_KEY \
--etherscan-api-key $ARBISCAN_API_KEY \
--verify \
src/TermsOfService.sol:TermsOfService
Save the address. Because Polygonscan is a hard mistress and tends to crash, verify manually:
export CONTRACT_ADDRESS=0xbe1418df0bAd87577de1A41385F19c6e77312780
scripts/verify-deployment.sh
The INITIAL_ACCEPTANCE_MESSAGE placeholder terms of service message is used.
Get the hash of the message:
ipython
Then type %cpaste
and copy-paste in:
from terms_of_service.acceptance_message import INITIAL_ACCEPTANCE_MESSAGE, get_signing_hash
new_line_escaped_msg = INITIAL_ACCEPTANCE_MESSAGE.replace("\n", "\\n")
print("Paste to your shell:")
print("")
print(f"""export ACCEPTANCE_MESSAGE_HASH={get_signing_hash(INITIAL_ACCEPTANCE_MESSAGE).hex()}""")
print(f"""export ACCEPTANCE_MESSAGE="{new_line_escaped_msg}" """)
export ACCEPTANCE_MESSAGE_HASH= # Copy from above output
export ACCEPTANCE_MESSAGE= # Copy from above output
export TERMS_OF_SERVICE_VERSION=1
export CONTRACT_ADDRESS=0xbe1418df0bAd87577de1A41385F19c6e77312780 # Set your deployed contract
Then set the initial version:
cast send \
--private-key $DEPLOY_PRIVATE_KEY \
--rpc-url $JSON_RPC_POLYGON \
$CONTRACT_ADDRESS \
"updateTermsOfService(uint16,bytes32,string)" \
"$TERMS_OF_SERVICE_VERSION" \
"$ACCEPTANCE_MESSAGE_HASH" \
"$ACCEPTANCE_MESSAGE"
You can also run the above command using scripts/set-terms-of-service.sh. The script will complain if you have some variables unset.
See here troubleshooting if cast send fails.
With ipython
:
from terms_of_service.acceptance_message import INITIAL_ACCEPTANCE_MESSAGE, get_signing_hash
NEW_ACCEPTANCE_MESSAGE="""Update: December 23th, 2023
In our ongoing commitment to adhere to legal regulations, we will restrict IP addresses located in certain jurisdictions from accessing our application’s frontend user interface. These jurisdictions include: United States, United Kingdom, Cuba, Iran, North Korea, Syria and Russia. Thank you for your understanding and ongoing support
Last Modified: December 23rd, 2023"""
new_line_escaped_msg = NEW_ACCEPTANCE_MESSAGE.replace("\n", "\\n")
print("Paste to your shell:")
print("")
print(f"""export ACCEPTANCE_MESSAGE_HASH={get_signing_hash(NEW_ACCEPTANCE_MESSAGE).hex()}""")
print(f"""export ACCEPTANCE_MESSAGE="{new_line_escaped_msg}" """)
print(f"""export TERMS_OF_SERVICE_VERSION=2""")
Then run:
scripts/set-terms-of-service.sh
- Configure environment vars
DEPLOY_PRIVATE_KEY
andJSON_RPC_POLYGON
,$CONTRACT_ADDRESS
- Get the latest Terms of Service version from the smart contract using PolygonScan:m https://polygonscan.com/address/0xbe1418df0bAd87577de1A41385F19c6e77312780#readContract
- Bump the version up by one
- Get the Microsoft Word document from a laywer (lawyers love Microsoft Word)
- Convert to Markdown using e.g. https://word2md.com/
- Checkout frontend repo
- Add the file as .txt file to
lib/assets/tos/
e.g.lib/assets/tos/2024-03-20.txt
- Set environment variables as in update.py
- Run
python scripts/update.py
to change on-chain state and get a new hash - Update
lib/assets/tos/tos-map.js
Example (Polygon):
# TOS version will be automatically picked from the smart contract
poetry shell
export TOS_DATE=2024-03-20
export CONTRACT_ADDRESS=0xbe1418df0bAd87577de1A41385F19c6e77312780
export JSON_RPC_POLYGON=
export DEPLOY_PRIVATE_KEY=
python scripts/update.py
Example (Ethereum):
# TOS version will be automatically picked from the smart contract
poetry shell
export TOS_DATE=2024-03-20
export CONTRACT_ADDRESS=0xd63c1bE9D8B56CCcD6fd2Dd9F9c030c6a9916f5F
export JSON_RPC_POLYGON=
export DEPLOY_PRIVATE_KEY=
python scripts/update-ethereum.py
## Deployment
A deployment can be found on Polygon [0xbe1418df0bAd87577de1A41385F19c6e77312780](https://polygonscan.com/address/0xbe1418df0bAd87577de1A41385F19c6e77312780).
## More information
- [Join Discord for any questions](https://tradingstrategy.ai/community).
- [Watch tutorials on YouTube](https://www.youtube.com/@tradingstrategyprotocol)
- [Follow on Twitter](https://twitter.com/TradingProtocol)
- [Follow on Telegram](https://t.me/trading_protocol)
- [Follow on LinkedIn](https://www.linkedin.com/company/trading-strategy/)