The primary smart contract development language is Solidity. However, this contains many, many footguns that the developers of Stacks have tried to fix. This post goes into he design of their custom language Clarity, and the vulnerabilities that it helps prevent.
The most famous vulnerability in Solidity is reentrancy. This is when a smart contract can call into another contract that eventually recalls your contract. This allows for the manipulation of the state that shouldn't be possible. Clarity doesn't allow for reentrancy at all. Integer overflows/underflows are prevented at the VM level as well.
Clarity requires external contract calls to be explicitly handled. This ensures that errors are handled properly. On top of this, all functions return something similar to a Result type in Rust. This makes the error handling very explicit in Clarity.
All code in Clarity knows the exact amount of gas before execution. To do this, unbounded iterations and dynamic lists are not possible. This prevents many standard classes of DoS vulnerabilities in Solidity. Clarity contains a native VRF function that the VM can call to obtain actual random data. This prevents weird randomness vulnerabilities like in Ethereum-based blockchains.
The final section is my favorite: unknown unknowns. To prevent users from getting exploited, they have post-conditions on the outcome of the contract execution. If these are violated, then the contract just fails. This helps proactively protect assets even if you don't know the vector.
Overall, a good post on the benefits of the Clarity language.