Skip to content

Instantly share code, notes, and snippets.

@poly-rodr
Last active November 27, 2025 07:41
Show Gist options
  • Select an option

  • Save poly-rodr/44313920481de58d5a3f6d1f8226bd5e to your computer and use it in GitHub Desktop.

Select an option

Save poly-rodr/44313920481de58d5a3f6d1f8226bd5e to your computer and use it in GitHub Desktop.
CLOB Allowance Setting Python + Neg Risk
from web3 import Web3
from web3.constants import MAX_INT
from web3.middleware import geth_poa_middleware
rpc_url = "" # Polygon rpc url
priv_key = "" # Polygon account private key (needs some MATIC)
pub_key = "" # Polygon account public key corresponding to private key
chain_id = 137
erc20_approve = """[{"constant": false,"inputs": [{"name": "_spender","type": "address" },{ "name": "_value", "type": "uint256" }],"name": "approve","outputs": [{ "name": "", "type": "bool" }],"payable": false,"stateMutability": "nonpayable","type": "function"}]"""
erc1155_set_approval = """[{"inputs": [{ "internalType": "address", "name": "operator", "type": "address" },{ "internalType": "bool", "name": "approved", "type": "bool" }],"name": "setApprovalForAll","outputs": [],"stateMutability": "nonpayable","type": "function"}]"""
usdc_address = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
ctf_address = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
web3 = Web3(Web3.HTTPProvider(rpc_url))
web3.middleware_onion.inject(geth_poa_middleware, layer=0)
nonce = web3.eth.getTransactionCount(pub_key)
usdc = web3.eth.contract(address=usdc_address, abi=erc20_approve)
ctf = web3.eth.contract(address=ctf_address, abi=erc1155_set_approval)
# CTF Exchange
raw_usdc_approve_txn = usdc.functions.approve("0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", int(MAX_INT, 0)
).buildTransaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_usdc_approve_tx = web3.eth.account.sign_transaction(raw_usdc_approve_txn, private_key=priv_key)
send_usdc_approve_tx = web3.eth.send_raw_transaction(signed_usdc_approve_tx.rawTransaction)
usdc_approve_tx_receipt = web3.eth.wait_for_transaction_receipt(send_usdc_approve_tx, 600)
print(usdc_approve_tx_receipt)
nonce = web3.eth.getTransactionCount(pub_key)
raw_ctf_approval_txn = ctf.functions.setApprovalForAll("0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", True).buildTransaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_ctf_approval_tx = web3.eth.account.sign_transaction(raw_ctf_approval_txn, private_key=priv_key)
send_ctf_approval_tx = web3.eth.send_raw_transaction(signed_ctf_approval_tx.rawTransaction)
ctf_approval_tx_receipt = web3.eth.wait_for_transaction_receipt(send_ctf_approval_tx, 600)
print(ctf_approval_tx_receipt)
nonce = web3.eth.getTransactionCount(pub_key)
# Neg Risk CTF Exchange
raw_usdc_approve_txn = usdc.functions.approve("0xC5d563A36AE78145C45a50134d48A1215220f80a", int(MAX_INT, 0)
).buildTransaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_usdc_approve_tx = web3.eth.account.sign_transaction(raw_usdc_approve_txn, private_key=priv_key)
send_usdc_approve_tx = web3.eth.send_raw_transaction(signed_usdc_approve_tx.rawTransaction)
usdc_approve_tx_receipt = web3.eth.wait_for_transaction_receipt(send_usdc_approve_tx, 600)
print(usdc_approve_tx_receipt)
nonce = web3.eth.getTransactionCount(pub_key)
raw_ctf_approval_txn = ctf.functions.setApprovalForAll("0xC5d563A36AE78145C45a50134d48A1215220f80a", True).buildTransaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_ctf_approval_tx = web3.eth.account.sign_transaction(raw_ctf_approval_txn, private_key=priv_key)
send_ctf_approval_tx = web3.eth.send_raw_transaction(signed_ctf_approval_tx.rawTransaction)
ctf_approval_tx_receipt = web3.eth.wait_for_transaction_receipt(send_ctf_approval_tx, 600)
print(ctf_approval_tx_receipt)
nonce = web3.eth.getTransactionCount(pub_key)
# Neg Risk Adapter
raw_usdc_approve_txn = usdc.functions.approve("0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296", int(MAX_INT, 0)
).buildTransaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_usdc_approve_tx = web3.eth.account.sign_transaction(raw_usdc_approve_txn, private_key=priv_key)
send_usdc_approve_tx = web3.eth.send_raw_transaction(signed_usdc_approve_tx.rawTransaction)
usdc_approve_tx_receipt = web3.eth.wait_for_transaction_receipt(send_usdc_approve_tx, 600)
print(usdc_approve_tx_receipt)
nonce = web3.eth.getTransactionCount(pub_key)
raw_ctf_approval_txn = ctf.functions.setApprovalForAll("0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296", True).buildTransaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_ctf_approval_tx = web3.eth.account.sign_transaction(raw_ctf_approval_txn, private_key=priv_key)
send_ctf_approval_tx = web3.eth.send_raw_transaction(signed_ctf_approval_tx.rawTransaction)
ctf_approval_tx_receipt = web3.eth.wait_for_transaction_receipt(send_ctf_approval_tx, 600)
print(ctf_approval_tx_receipt)
@to1dev
Copy link

to1dev commented Sep 14, 2025

Here’s a simple TypeScript script that performs the same allowance operation.

To make everything work smoothly, you'll need to…

  1. Install viem (npm install viem / bun add viem)
  2. Transfer some USDC.e to your wallet (withdraw USDC.e to your wallet from your polymarket dashboard)
import {
    createPublicClient,
    createWalletClient,
    http,
    parseAbi,
    maxUint256,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { polygon } from "viem/chains";

// ==== Basic Config ====
const rpcUrl = process.env.POLYGON_RPC;
const privKey = process.env.PRIVATE_KEY as `0x${string}`;
const account = privateKeyToAccount(privKey);

const publicClient = createPublicClient({
    chain: polygon,
    transport: http(rpcUrl),
});

const walletClient = createWalletClient({
    account,
    chain: polygon,
    transport: http(rpcUrl),
});

// ==== ABI ====
const erc20Abi = parseAbi([
    "function approve(address spender, uint256 value) returns (bool)",
]);

const erc1155Abi = parseAbi([
    "function setApprovalForAll(address operator, bool approved)",
]);

// ==== Contract Addresses ====
const usdc = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
const ctf = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045";

const targets: `0x${string}`[] = [
    "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", // CTF Exchange
    "0xC5d563A36AE78145C45a50134d48A1215220f80a", // Neg Risk CTF Exchange
    "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296", // Neg Risk Adapter
];

// ==== Execute approve / setApprovalForAll ====
async function main() {
    console.log(`🔑 Using account: ${account.address}`);

    for (const target of targets) {
        console.log(`🔑 Granting approvals to ${target}...`);

        // --- 1. ERC20 approve ---
        const { request: approveReq } = await publicClient.simulateContract({
            address: usdc,
            abi: erc20Abi,
            functionName: "approve",
            args: [target, maxUint256],
            account, // 👈 Must pass account to avoid zero address
        });

        const approveHash = await walletClient.writeContract(approveReq);
        const approveReceipt = await publicClient.waitForTransactionReceipt({
            hash: approveHash,
        });
        console.log("✅ USDC approve tx:", approveReceipt.transactionHash);

        // --- 2. ERC1155 setApprovalForAll ---
        const { request: setApprovalReq } = await publicClient.simulateContract(
            {
                address: ctf,
                abi: erc1155Abi,
                functionName: "setApprovalForAll",
                args: [target, true],
                account, // 👈 Must also pass account here
            }
        );

        const setApprovalHash = await walletClient.writeContract(
            setApprovalReq
        );
        const setApprovalReceipt = await publicClient.waitForTransactionReceipt(
            { hash: setApprovalHash }
        );
        console.log(
            "✅ CTF setApproval tx:",
            setApprovalReceipt.transactionHash
        );
    }
}

main().catch((err) => {
    console.error("❌ Error:", err);
});

@skewliness
Copy link

以下是一个简单的 TypeScript 脚本,可以执行相同的权限操作。

为了确保一切顺利进行,你需要……

  1. 安装 viem(npm install viem/bun add viem)
  2. 将一些 USDC.e 转入您的钱包(从您的 Polymarket 控制面板提取 USDC.e 到您的钱包)
import {
    createPublicClient,
    createWalletClient,
    http,
    parseAbi,
    maxUint256,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { polygon } from "viem/chains";

// ==== Basic Config ====
const rpcUrl = process.env.POLYGON_RPC;
const privKey = process.env.PRIVATE_KEY as `0x${string}`;
const account = privateKeyToAccount(privKey);

const publicClient = createPublicClient({
    chain: polygon,
    transport: http(rpcUrl),
});

const walletClient = createWalletClient({
    account,
    chain: polygon,
    transport: http(rpcUrl),
});

// ==== ABI ====
const erc20Abi = parseAbi([
    "function approve(address spender, uint256 value) returns (bool)",
]);

const erc1155Abi = parseAbi([
    "function setApprovalForAll(address operator, bool approved)",
]);

// ==== Contract Addresses ====
const usdc = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
const ctf = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045";

const targets: `0x${string}`[] = [
    "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", // CTF Exchange
    "0xC5d563A36AE78145C45a50134d48A1215220f80a", // Neg Risk CTF Exchange
    "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296", // Neg Risk Adapter
];

// ==== Execute approve / setApprovalForAll ====
async function main() {
    console.log(`🔑 Using account: ${account.address}`);

    for (const target of targets) {
        console.log(`🔑 Granting approvals to ${target}...`);

        // --- 1. ERC20 approve ---
        const { request: approveReq } = await publicClient.simulateContract({
            address: usdc,
            abi: erc20Abi,
            functionName: "approve",
            args: [target, maxUint256],
            account, // 👈 Must pass account to avoid zero address
        });

        const approveHash = await walletClient.writeContract(approveReq);
        const approveReceipt = await publicClient.waitForTransactionReceipt({
            hash: approveHash,
        });
        console.log("✅ USDC approve tx:", approveReceipt.transactionHash);

        // --- 2. ERC1155 setApprovalForAll ---
        const { request: setApprovalReq } = await publicClient.simulateContract(
            {
                address: ctf,
                abi: erc1155Abi,
                functionName: "setApprovalForAll",
                args: [target, true],
                account, // 👈 Must also pass account here
            }
        );

        const setApprovalHash = await walletClient.writeContract(
            setApprovalReq
        );
        const setApprovalReceipt = await publicClient.waitForTransactionReceipt(
            { hash: setApprovalHash }
        );
        console.log(
            "✅ CTF setApproval tx:",
            setApprovalReceipt.transactionHash
        );
    }
}

main().catch((err) => {
    console.error("❌ Error:", err);
});

What I don't understand is that it's actually just using Metamask to log in to PolyMarkets. The actual transaction address is the address generated by PM. Why put USDC on Metamask?

@x011
Copy link

x011 commented Nov 18, 2025

This script worked for me with web3 version 6.14.0. Allowance was was updated correctly.

# works with web3===6.14.0
from web3 import Web3
from web3.constants import MAX_INT
from web3.middleware import geth_poa_middleware

rpc_url = "https://polygon-rpc.com" # Polygon rpc url 
priv_key = "" # Polygon account private key (needs some MATIC)
pub_key = "" # Polygon account public key corresponding to private key
chain_id = 137

erc20_approve = """[{"constant": false,"inputs": [{"name": "_spender","type": "address" },{ "name": "_value", "type": "uint256" }],"name": "approve","outputs": [{ "name": "", "type": "bool" }],"payable": false,"stateMutability": "nonpayable","type": "function"}]"""
erc1155_set_approval = """[{"inputs": [{ "internalType": "address", "name": "operator", "type": "address" },{ "internalType": "bool", "name": "approved", "type": "bool" }],"name": "setApprovalForAll","outputs": [],"stateMutability": "nonpayable","type": "function"}]"""

usdc_address = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" # MATIC collateral
ctf_address = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045" # MATIC conditionalTokens

web3 = Web3(Web3.HTTPProvider(rpc_url))
web3.middleware_onion.inject(geth_poa_middleware, layer=0)

nonce = web3.eth.get_transaction_count(pub_key)

usdc = web3.eth.contract(address=usdc_address, abi=erc20_approve)
ctf = web3.eth.contract(address=ctf_address, abi=erc1155_set_approval)


# CTF Exchange
raw_usdc_approve_txn = usdc.functions.approve("0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", int(MAX_INT, 0)
).build_transaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_usdc_approve_tx = web3.eth.account.sign_transaction(raw_usdc_approve_txn, private_key=priv_key)
send_usdc_approve_tx = web3.eth.send_raw_transaction(signed_usdc_approve_tx.rawTransaction)
usdc_approve_tx_receipt = web3.eth.wait_for_transaction_receipt(send_usdc_approve_tx, 600)
print(usdc_approve_tx_receipt)

nonce = web3.eth.get_transaction_count(pub_key)

raw_ctf_approval_txn = ctf.functions.setApprovalForAll("0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", True).build_transaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_ctf_approval_tx = web3.eth.account.sign_transaction(raw_ctf_approval_txn, private_key=priv_key)
send_ctf_approval_tx = web3.eth.send_raw_transaction(signed_ctf_approval_tx.rawTransaction)
ctf_approval_tx_receipt = web3.eth.wait_for_transaction_receipt(send_ctf_approval_tx, 600)
print(ctf_approval_tx_receipt)

nonce = web3.eth.get_transaction_count(pub_key)

# Neg Risk CTF Exchange
raw_usdc_approve_txn = usdc.functions.approve("0xC5d563A36AE78145C45a50134d48A1215220f80a", int(MAX_INT, 0)
).build_transaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_usdc_approve_tx = web3.eth.account.sign_transaction(raw_usdc_approve_txn, private_key=priv_key)
send_usdc_approve_tx = web3.eth.send_raw_transaction(signed_usdc_approve_tx.rawTransaction)
usdc_approve_tx_receipt = web3.eth.wait_for_transaction_receipt(send_usdc_approve_tx, 600)
print(usdc_approve_tx_receipt)

nonce = web3.eth.get_transaction_count(pub_key)

raw_ctf_approval_txn = ctf.functions.setApprovalForAll("0xC5d563A36AE78145C45a50134d48A1215220f80a", True).build_transaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_ctf_approval_tx = web3.eth.account.sign_transaction(raw_ctf_approval_txn, private_key=priv_key)
send_ctf_approval_tx = web3.eth.send_raw_transaction(signed_ctf_approval_tx.rawTransaction)
ctf_approval_tx_receipt = web3.eth.wait_for_transaction_receipt(send_ctf_approval_tx, 600)
print(ctf_approval_tx_receipt)

nonce = web3.eth.get_transaction_count(pub_key)

# Neg Risk Adapter
raw_usdc_approve_txn = usdc.functions.approve("0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296", int(MAX_INT, 0)
).build_transaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_usdc_approve_tx = web3.eth.account.sign_transaction(raw_usdc_approve_txn, private_key=priv_key)
send_usdc_approve_tx = web3.eth.send_raw_transaction(signed_usdc_approve_tx.rawTransaction)
usdc_approve_tx_receipt = web3.eth.wait_for_transaction_receipt(send_usdc_approve_tx, 600)
print(usdc_approve_tx_receipt)

nonce = web3.eth.get_transaction_count(pub_key)

raw_ctf_approval_txn = ctf.functions.setApprovalForAll("0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296", True).build_transaction({"chainId": chain_id, "from": pub_key, "nonce": nonce})
signed_ctf_approval_tx = web3.eth.account.sign_transaction(raw_ctf_approval_txn, private_key=priv_key)
send_ctf_approval_tx = web3.eth.send_raw_transaction(signed_ctf_approval_tx.rawTransaction)
ctf_approval_tx_receipt = web3.eth.wait_for_transaction_receipt(send_ctf_approval_tx, 600)
print(ctf_approval_tx_receipt)

Thank you, this worked for me with python3.11 and web3===6.14.0

@ShayenK
Copy link

ShayenK commented Nov 27, 2025

Hi This Version wasn't working for me but I made this version that works for the most recent version of web3 as of 27/11/2025

Extra Tips to Help with a Successful Bot:

  • make sure you have USDC.e (contract addy: 0x2791bca1f2de4661ed88a30c99a7a9449aa84174) for the actual trading execution otherwise it will still show balance / allowance error (NOT the other USDC contract addy: 0x3c499c542cef5e3811e1192ce70d8cc03d5c3359)
  • had to also test using a higher fill price i.e. 0.55 as opposed to 0.5 (just when testing)
  • MOST IMPORTANTLY: build out a redemption system for settlement back into your wallet -> last thing you want is to not be able to claim the money that you won
import os
from web3 import Web3
from web3.constants import MAX_INT
from web3.middleware import ExtraDataToPOAMiddleware  # Updated for web3.py v6+
from dotenv import load_dotenv
load_dotenv()

rpc_url = "https://polygon-rpc.com"
priv_key = ""  # Polygon account private key (needs some MATIC)
pub_key = ""  # Polygon account public key corresponding to private key
chain_id = 137

erc20_approve_abi = '[{"constant": false,"inputs": [{"name": "_spender","type": "address" },{ "name": "_value", "type": "uint256" }],"name": "approve","outputs": [{ "name": "", "type": "bool" }],"payable": false,"stateMutability": "nonpayable","type": "function"}]'
erc1155_set_approval_abi = '[{"inputs": [{ "internalType": "address", "name": "operator", "type": "address" },{ "internalType": "bool", "name": "approved", "type": "bool" }],"name": "setApprovalForAll","outputs": [],"stateMutability": "nonpayable","type": "function"}]'

usdc_address = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"  # USDC.e on Polygon
ctf_address = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"   # Conditional Tokens

web3 = Web3(Web3.HTTPProvider(rpc_url))
web3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)

# Get initial nonce
nonce = web3.eth.get_transaction_count(pub_key)

usdc = web3.eth.contract(address=usdc_address, abi=erc20_approve_abi)
ctf = web3.eth.contract(address=ctf_address, abi=erc1155_set_approval_abi)

# Helper to send and wait for tx
def send_and_wait(raw_tx):
    signed_tx = web3.eth.account.sign_transaction(raw_tx, private_key=priv_key)
    tx_hash = web3.eth.send_raw_transaction(signed_tx.raw_transaction)  # Fixed: raw_transaction
    receipt = web3.eth.wait_for_transaction_receipt(tx_hash, timeout=600)
    print(f"Success: {receipt.transactionHash.hex()} (status: {receipt.status})")
    return receipt

# === CTF Exchange ===
# USDC approve
raw_tx = usdc.functions.approve(
    "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", int(MAX_INT, 0)
).build_transaction({
    "chainId": chain_id,
    "from": pub_key,
    "nonce": nonce,
    "gasPrice": web3.eth.gas_price  # Auto gas price
})
send_and_wait(raw_tx)
nonce += 1

# CTF setApprovalForAll
raw_tx = ctf.functions.setApprovalForAll("0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", True).build_transaction({
    "chainId": chain_id,
    "from": pub_key,
    "nonce": nonce,
    "gasPrice": web3.eth.gas_price
})
send_and_wait(raw_tx)
nonce += 1

# === Neg Risk CTF Exchange ===
# USDC approve
raw_tx = usdc.functions.approve(
    "0xC5d563A36AE78145C45a50134d48A1215220f80a", int(MAX_INT, 0)
).build_transaction({
    "chainId": chain_id,
    "from": pub_key,
    "nonce": nonce,
    "gasPrice": web3.eth.gas_price
})
send_and_wait(raw_tx)
nonce += 1

# CTF setApprovalForAll
raw_tx = ctf.functions.setApprovalForAll("0xC5d563A36AE78145C45a50134d48A1215220f80a", True).build_transaction({
    "chainId": chain_id,
    "from": pub_key,
    "nonce": nonce,
    "gasPrice": web3.eth.gas_price
})
send_and_wait(raw_tx)
nonce += 1

# === Neg Risk Adapter ===
# USDC approve
raw_tx = usdc.functions.approve(
    "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296", int(MAX_INT, 0)
).build_transaction({
    "chainId": chain_id,
    "from": pub_key,
    "nonce": nonce,
    "gasPrice": web3.eth.gas_price
})
send_and_wait(raw_tx)
nonce += 1

# CTF setApprovalForAll
raw_tx = ctf.functions.setApprovalForAll("0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296", True).build_transaction({
    "chainId": chain_id,
    "from": pub_key,
    "nonce": nonce,
    "gasPrice": web3.eth.gas_price
})
send_and_wait(raw_tx)

print("All 6 approvals completed! Your wallet is now permanently set up for Polymarket trading.")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment