By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
Regulatory Landscape (SEC, MiCA, KYC/AML for Crypto) –?A practical, project?ready study guide Target audience: software engineers & finance professionals moving into Web3
Regulatory Landscape is the set of rules, guidance, and enforcement actions that governments and regulators (e.g., the U.S. SEC, the EU’s MiCA, and global KYC/AML bodies) apply to blockchain projects. In a decentralized world, these rules determine whether a token is treated as a security, how a DAO must disclose information, and what on?chain/off?chain checks you must run before letting users trade, lend, or mint NFTs. Real?world example: a DeFi lending platform that automatically blocks U.S. addresses from borrowing because the token it issues is deemed a security under SEC guidance.
```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.24;
import "@openzeppelin/contracts/access/AccessControl.sol";
contract KYCRegistry is AccessControl { bytes32 public constant ADMIN_ROLE = keccak256("ADMIN"); mapping(address => bytes32) public kycHash; // keccak256( off?chain data )
event KYCUpdated(address indexed user, bytes32 hash); constructor() { _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(ADMIN_ROLE, msg.sender); } function setKYC(address user, bytes32 hash) external onlyRole(ADMIN_ROLE) { kycHash[user] = hash; emit KYCUpdated(user, hash); } function isVerified(address user) external view returns (bool) { return kycHash[user] != bytes32(0); }
} ```
transferWithData
isControllable
canTransfer
setKYC
```js const { ethers } = require("ethers"); const KYC_ABI = [...] // ABI from the Solidity contract above const provider = new ethers.InfuraProvider("goerli", INFURA_KEY); const signer = new ethers.Wallet(PRIVATE_KEY, provider); const kyc = new ethers.Contract(KYC_ADDRESS, KYC_ABI, signer);
async function submitKYC(userAddr, kycPayload) { const hash = ethers.keccak256(ethers.toUtf8Bytes(JSON.stringify(kycPayload))); const tx = await kyc.setKYC(userAddr, hash); await tx.wait(); console.log(KYC recorded for ${userAddr}); } `` - Compliance Modifier (Solidity): A reusableonlyVerified` modifier that checks the KYC registry before allowing a function to run.
KYC recorded for ${userAddr}
`` - Compliance Modifier (Solidity): A reusable
solidity modifier onlyVerified(address user) { require(KYCRegistry(kyc).isVerified(user), "KYC not completed"); _; }
KYCRegistry
ERC1400
bash npx hardhat run scripts/deployKYC.js --network goerli3. Integrate Off?Chain KYC Provider – Build a Node.js service that calls the provider’s API, hashes the response, and invokes setKYC. Secure the endpoint with TLS and API?key authentication.4. Guard Sensitive Functions – Add the onlyVerified modifier (or canTransfer hook for ERC?1400) to any function that creates, transfers, or redeems tokens.
bash npx hardhat run scripts/deployKYC.js --network goerli
onlyVerified
solidity function mint(address to, uint256 amount) external onlyVerified(to) { … }5. Add AML Monitoring – Subscribe to on?chain analytics (e.g., Blockscan, Chainalysis) via webhooks; flag addresses that hit a risk threshold and automatically pause them using pause() from OpenZeppelin’s Pausable.6. Publish a Compliance White?Paper – For MiCA, host a publicly accessible PDF that includes the CASP licence, risk disclosures, and the KYC/AML process. Link to it from your dApp UI (e.g., a “Legal” modal).
solidity function mint(address to, uint256 amount) external onlyVerified(to) { … }
pause()
Pausable
Mistake: Using tx.origin for access control (e.g., require(tx.origin == owner)). Correction: Always use msg.sender or role?based checks; tx.origin can be spoofed through a malicious contract, breaking KYC guarantees.
tx.origin
require(tx.origin == owner)
msg.sender
Mistake: Storing raw personal data on?chain (e.g., full name, SSN). Correction: Store only a cryptographic hash; keep the PII off?chain to stay GDPR?compliant and avoid immutable privacy breaches.
Mistake: Assuming “decentralized” = “regulation?free”. Correction: Even permissionless protocols can be subject to securities law if the token’s economic characteristics meet the Howey criteria; always run a legal opinion before launch.
Mistake: Forgetting to pause the contract when a regulator issues a cease?and?desist. Correction: Implement OpenZeppelin’s Pausable and give the admin role to a multi?sig wallet so the team can instantly freeze all token activity.
Mistake: Hard?coding a single KYC provider address. Correction: Use an upgradeable proxy pattern for the registry so you can swap out the provider without redeploying the whole token contract.
“Explain the difference between a security token (ERC?1400) and a utility token (ERC?20) from a regulator’s perspective.” Look for: mention of profit?expectation, voting rights, registration/exemption, and built?in compliance hooks.
“How would you design a ‘compliant transfer’ function that respects both SEC and MiCA rules?” Expect a layered answer: KYC check-AML risk score-ERC?1400 canTransfer hook-Pausable fallback.
“What is the purpose of a ‘passport’ under MiCA, and how does it affect a dApp that wants to serve EU users?” Key points: single?state CASP licence, cross?border freedom, need to display licence number, and the dApp must still enforce KYC/AML per the host state.
“Why might a developer prefer delegatecall over call when implementing an upgradeable compliance module?” Answer should discuss storage layout preservation, gas efficiency, and the security risk of delegatecall (need for trusted implementation).
delegatecall
call
Scenario: A token contract uses require(tx.origin == owner) to restrict minting to the project founder. Answer: Dangerous – tx.origin can be hijacked by a malicious contract, allowing an attacker to bypass KYC and mint tokens.
Scenario: Your dApp stores a user’s passport number hash on?chain but never deletes it. A user requests removal under GDPR. Answer: You cannot delete immutable on?chain data; the correct approach is to store only a hash of a reference that can be revoked off?chain.
Scenario: After a regulator issues a cease?and?desist, you need to stop all token transfers instantly. Which OpenZeppelin contract helps? Answer: Pausable – call pause() from the admin multi?sig to freeze transfer and transferFrom functions.
transfer
transferFrom
unchecked {}
i++
You now have a ready?to?code, regulator?aware checklist that you can plug into any DeFi, NFT, or DAO project. Good luck building compliant Web3!
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.