I have a contact for each pair of overlapping shape proxies. The contacts are persistent over frames. When I update the broadphase and detect an overlapping pair I first check if I already created a contact for that pair. Each shape has a list of associated contacts. So I simply search the shorter list. Alternatively you could have a simple hashtable.
Next I create the new manifold. If the new manifold was created from the same features as the old one I match the new points with the old points using the clipping Ids. I don't use any heuristic based on distance or local contact points.
In order for this to work you need relatively stable features. You need to favor one face over the other and face contacts over edge contacts. You can find an example here (b2CollidePolygons): https://github.com/erincatto/Box2D/blob/master/Box2D/Box2D/Collision/b2CollidePolygon.cpp
const float32 k_tol = 0.1f * b2_linearSlop;
if (separationB > k_rel * separationA + k_tol)
I suggest using combined relative and absolute tolerances and incorporate the edge separation as well:
http://realtimecollisiondetection.net/pubs/Tolerances/
You can find an example of the contact matching here:
https://github.com/erincatto/Box2D/blob/master/Box2D/Box2D/Dynamics/Contacts/b2Contact.cpp
There is also some example lib called Box2D Lite which is even easier to follow. It is part of one of Erin's presentations here (I think in GDC 2006):
http://box2d.org/downloads/
As a side note:
The pair management depends a bit on your broadphase. SAP has natural begin, persist, and end overlap events. When using a dynamic tree things are a bit different. These are really just implementation details. You just need a way to find existing contacts between pairs. Then simply match the new manifold points with the old ones.
We did discuss the contact ID creation at the end of this thread:
http://www.gamedev.net/topic/667499-3d-sat-problem/
HTH,
-Dirk